I have an array arr_ = [['a', 'b'], ['x', 'y']]
I want to put at the beginning of each subarray the character !
so it should look kile this [['!', 'a', 'b'], ['!', 'x', 'y']]
this is what i've done so far:
def concat(*args):
return ['!', *args]
arr_ = [['a', 'b'], ['x', 'y']]
n = map(concat, arr_)
print(list(n))
but the result is [['!', ['a', 'b']], ['!', ['x', 'y']]]
What should i do?
just remove the * in the argument of the mapper:
def concat(args):
return ['!', *args]
arr_ = [['a', 'b'], ['x', 'y']]
n = map(concat, arr_)
list(n)
>>> [['!', 'a', 'b'], ['!', 'x', 'y']]
what happening is you packing and then unpacking the lists in each iteration...
when you add * to the argument you turn in into a list that contains 1 item.
when u skip this stage you can the real list and unpack it with * in the list statement return ['!', *args] which is equal to do : ['!'] + args to add the '!' in the beginning
this would work as expected if you did def concat(args):
What's happening is if you do *args as the parameter, every parameter you pass in will be put into a list stored in *args
And you're passing in things like ['a', 'b']
So that will be put into a list so really args is: [['a', 'b']]
and then in your return you unpack that list
but it only contains one element, that being the original list
so you get ['!', ['a', 'b']]
just a note, map is generally considered unpythonic since we also have list comprehensions:
n = [concat(inner) for inner in arr_]
you could go one step further and do this:
n = [['!'] + inner for inner in arr_]
I don't know how to explain the bug in your code. But I found another way to do it.
arr = [['a', 'b'], ['x', 'y']]
X = []
for i in arr:
X.append(['!'] + i)
print(X)
Output:
[['!', 'a', 'b'], ['!', 'x', 'y']]
Using List Comprehension:
arr = [['a', 'b'], ['x', 'y']]
X = [['!'] + x for x in arr]
print(X)
Output:
[['!', 'a', 'b'], ['!', 'x', 'y']]
Related
Given a list of strings:
haystack = ['hay','hay','hay','needle','x','y','z','hay','hay','hay','hay','needle','a','b','c']
Question
How would I form a new list of strings that contain, say, only the three adjacent elements (to the right) of every 'needle' occurrence within haystack?
Find all the indices of "needle" and take 3 values right the indices.
# Get all indices of "needle"
idx = [idx for idx, val in enumerate(haystack) if val=="needle"]
#idx -> [3, 11]
# Take 3 values right of each index in `idx`.
[val for i in idx for val in haystack[i: i+4]]
# ['needle', 'x', 'y', 'z', 'needle', 'a', 'b', 'c']
# want it to be a list of list
[haystack[i: i+4] for i in idx]
# [['needle', 'x', 'y', 'z'], ['needle', 'a', 'b', 'c']]
# Want to exclude the "needle"
[val for i in idx for val in haystack[i+1: i+4]]
# ['x', 'y', 'z', 'a', 'b', 'c']
This is a kind of hacky solution, but it works with only one pass through the list.
it = iter(haystack)
output = [[next(it), next(it), next(it)] for s in it if s == 'needle']
# [['x', 'y', 'z'], ['a', 'b', 'c']]
This is essentially the short-form of the following:
it = iter(haystack)
output = []
while True:
try:
elem = next(it)
if elem == 'needle':
output.append([next(it), next(it), next(it)])
except StopIteration:
break
note that, in the short form, you'll get a StopIteration error if there are fewer than three elements following a 'needle'.
A simple list comprehension with list slicing seems to work as well:
out = [haystack[i+1:i+4] for i, x in enumerate(haystack) if x == 'needle']
Output:
[['x', 'y', 'z'], ['a', 'b', 'c']]
If I understood correctly then you want this...
for i in [i for i,ele in enumerate(haystack) if ele=="needle"]:
Out.extend(haystack[i+1:i+4])
print(Out)
Output
['x', 'y', 'z', 'a', 'b', 'c']
how do I convert all the numerical strings, inside a list of list that contains both alphabetical, and numerical strings, into an integer?
My Output:
[['69', ' Test', 'Results'], ['A', 'B', 'C'], ['D', '420', 'F']]
Intended Output:
[[69, ' Test', 'Results'], ['A', 'B', 'C'], ['D', 420, 'F']]
Note that my code reads a CSV file. Thanks everyone
def get_csv_as_table(a, b):
s = False
import csv
with open(a) as csv_file:
file_reader = csv.reader(csv_file, delimiter=b)
member = list(file_reader)
print(member)
print ("Enter filename: ")
a = input()
print ("Enter the delimiter: ")
b = input()
get_csv_as_table(a, b)
You can use list comprehension to achieve this. The only minor downside to this is that you will be creating a new list for this instead of modifying the existing list.
my_list = [['69', 'Test', 'Results'], ['A', 'B', 'C'], ['D', '420', 'F']]
filtered_list = [
[int(item) if item.isdigit() else item for item in sub_list]
for sub_list in my_list
]
If you want to edit the list in-place, you can use traditional for-loop. The following code will edit the existing list without creating a new list. This could turn out to be useful in case you have a large list.
my_list = [['69', 'Test', 'Results'], ['A', 'B', 'C'], ['D', '420', 'F']]
for i in range(len(my_list)):
for j in range(len(my_list[i])):
if my_list[i][j].isdigit():
my_list[i][j] = int(my_list[i][j])
str.isdigit() checks if a given string is a number or not. An important note to keep in mind is that, it does not work for floating-point numbers, just integers. Once the condition passes, the item is converted to integer.
Yoy have to combine 2 levels of list-comprehension and use str.isdigit()
values = [
[int(val) if val.isdigit() else val for val in row]
for row in values
]
Try with 2-level list comprehension and int()+.isdigit() power combo in list comprehension ;-)
l=[['69', ' Test', 'Results'], ['A', 'B', 'C'], ['D', '420', 'F']]
l=[[int(y) if y.isdigit() else y for y in x] for x in l]
print(l)
Output:
[[69, ' Test', 'Results'], ['A', 'B', 'C'], ['D', 420, 'F']]
.isdigit() only works on string representation of pure integers, In case if you have floats too then replace '.' to nothing ;-)
l=[['69', ' Test', 'Results'], ['A', 'B', 'C'], ['D', '420', 'F']]
l=[[float(y) if y.replace('.','').isdigit() else y for y in x] for x in l]
print(l)
Output:
[[69.0, ' Test', 'Results'], ['A', 'B', 'C'], ['D', 420.0, 'F']]
I have a problem trying to transform a list.
The original list is like this:
[['a','b','c',''],['c','e','f'],['c','g','h']]
now I want to make the output like this:
[['a','b','c','e','f'],['a','b','c','g','h']]
When the blank is found ( '' ) merge the three list into two lists.
I need to write a function to do this for me.
Here is what I tried:
for x in mylist:
if x[len(x) - 1] == '':
m = x[len(x) - 2]
for y in mylist:
if y[0] == m:
combine(x, y)
def combine(x, y):
for m in y:
if not m in x:
x.append(m)
return(x)
but its not working the way I want.
try this :
mylist = [['a','b','c',''],['c','e','f'],['c','g','h']]
def combine(x, y):
for m in y:
if not m in x:
x.append(m)
return(x)
result = []
for x in mylist:
if x[len(x) - 1] == '':
m = x[len(x) - 2]
for y in mylist:
if y[0] == m:
result.append(combine(x[0:len(x)-2], y))
print(result)
your problem was with
combine(x[0:len(x)-2], y)
output :
[['a', 'b', 'c', 'e', 'f'], ['a', 'b', 'c', 'g', 'h']]
So you basically want to merge 2 lists? If so, you can use one of 2 ways :
Either use the + operator, or use the
extend() method.
And then you put it into a function.
I made it with standard library only with comments. Please refer it.
mylist = [['a','b','c',''],['c','e','f'],['c','g','h']]
# I can't make sure whether the xlist's item is just one or not.
# So, I made it to find all
# And, you can see how to get the last value of a list as [-1]
xlist = [x for x in mylist if x[-1] == '']
ylist = [x for x in mylist if x[-1] != '']
result = []
# combine matrix of x x y
for x in xlist:
for y in ylist:
c = x + y # merge
c = [i for i in c if i] # drop ''
c = list(set(c)) # drop duplicates
c.sort() # sort
result.append(c) # add to result
print (result)
The result is
[['a', 'b', 'c', 'e', 'f'], ['a', 'b', 'c', 'g', 'h']]
Your code almost works, except you never do anything with the result of combine (print it, or add it to some result list), and you do not remove the '' element. However, for a longer list, this might be a bit slow, as it has quadratic complexity O(n²).
Instead, you can use a dictionary to map first elements to the remaining elements of the lists. Then you can use a loop or list comprehension to combine the lists with the right suffixes:
lst = [['a','b','c',''],['c','e','f'],['c','g','h']]
import collections
replacements = collections.defaultdict(list)
for first, *rest in lst:
replacements[first].append(rest)
result = [l[:-2] + c for l in lst if l[-1] == "" for c in replacements[l[-2]]]
# [['a', 'b', 'c', 'e', 'f'], ['a', 'b', 'c', 'g', 'h']]
If the list can have more than one placeholder '', and if those can appear in the middle of the list, then things get a bit more complicated. You could make this a recursive function. (This could be made more efficient by using an index instead of repeatedly slicing the list.)
def replace(lst, last=None):
if lst:
first, *rest = lst
if first == "":
for repl in replacements[last]:
yield from replace(repl + rest)
else:
for res in replace(rest, first):
yield [first] + res
else:
yield []
for l in lst:
for x in replace(l):
print(x)
Output for lst = [['a','b','c','','b',''],['c','b','','e','f'],['c','g','b',''],['b','x','y']]:
['a', 'b', 'c', 'b', 'x', 'y', 'e', 'f', 'b', 'x', 'y']
['a', 'b', 'c', 'g', 'b', 'x', 'y', 'b', 'x', 'y']
['c', 'b', 'x', 'y', 'e', 'f']
['c', 'g', 'b', 'x', 'y']
['b', 'x', 'y']
try my solution
although it will change the order of list but it's quite simple code
lst = [['a', 'b', 'c', ''], ['c', 'e', 'f'], ['c', 'g', 'h']]
lst[0].pop(-1)
print([list(set(lst[0]+lst[1])), list(set(lst[0]+lst[2]))])
I done the following Python script which should return a list of sublists.
def checklisting(inputlist, repts):
result = []
temprs = []
ic = 1;
for x in inputlist
temprs.append(x)
ic += 1
if ic == repts:
ic = 1
result.append(temprs)
return result
Example: If I called the function with the following arguments:
checklisting(['a', 'b', 'c', 'd'], 2)
it would return
[['a', 'b'], ['c', 'd']]
or if I called it like:
checklisting(['a', 'b', 'c', 'd'], 4)
it would return
[['a', 'b', 'c', 'd']]
However what it returns is a weird huge list:
>>> l.checklisting(['a','b','c','d'], 2)
[['a', 'b', 'c', 'd'], ['a', 'b', 'c', 'd'], ['a', 'b', 'c', 'd'], ['a', 'b', 'c', 'd']]
Someone please help! I need that script to compile a list with the data:
['water tax', 20, 'per month', 'electric tax', 1, 'per day']
The logic behind it is that it would separe sequences in the list the size of repts into sublists so it can be better and easier organized. I don't want arbitrary chunks of sublists as these in the other question don't specify the size of the sequence correctly.
Your logic is flawed.
Here are the bugs: You keep appending to temprs. Once repts is reached, you need to remove elements from temprs. Also, list indexes start at 0 so ic should be 0 instead of 1
Replace your def with:
def checklisting(inputlist, repts):
result = []
temprs = []
ic = 0;
for x in inputlist:
temprs.append(x)
ic += 1
if ic == repts:
ic = 0
result.append(temprs)
temprs = []
return result
Here is link to working demo of code above
def split_into_sublists(list_, size):
return list(map(list,zip(*[iter(list_)]*size)))
#[iter(list_)]*size this creates size time lists, if
#size is 3 three lists will be created.
#zip will zip the lists into tuples
#map will covert tuples to lists.
#list will convert map object to list.
print(split_into_sublists(['a', 'b', 'c', 'd'], 2))
[['a', 'b'], ['c', 'd']]
print(split_into_sublists(['a', 'b', 'c', 'd'], 4))
[['a', 'b', 'c', 'd']]
I got lost in your code. I think the more Pythonic approach is to slice the list. And I can never resist list comprehensions.
def checklisting(inputlist, repts):
return [ input_list[i:i+repts] for i in range(int(len(input_list)/repts)) ]
Given an array say x = ['A','I','R']
I would want output as an
[['A','I','R'],['A','I'],['I','R'],['A'],['I'],['R']]
What I don't want as output is :
[['A','I','R'],['A','I'],['I','R'],['A','R'],['A'],['I'],['R']] # extra ['A','R'] which is not in sequence .
Below is the code which gives the output I don't want:
letter_list = [a for a in str]
all_word = []
for i in xrange(0,len(letter_list)):
all_word = all_word + (map(list, itertools.combinations(letter_list,i))) # dont use append. gives wrong result.
all_word = filter(None,all_word) # remove empty combination
all_word = all_word + [letter_list] # add original list
My point is I only want combinations of sequences. Is there any way to use itertools or should I write custom function ?
Yes, you can use itertools:
>>> x = ['A', 'I', 'R']
>>> xs = [x[i:j] for i, j in itertools.combinations(range(len(x)+1), 2)]
>>> xs
[['A'], ['A', 'I'], ['A', 'I', 'R'], ['I'], ['I', 'R'], ['R']]
>>> sorted(xs, key=len, reverse=True)
[['A', 'I', 'R'], ['A', 'I'], ['I', 'R'], ['A'], ['I'], ['R']]
Credit: answer by hochl
Try to use yield:
x = ['A','I','R']
def groupme(x):
s = tuple(x)
for size in range(1, len(s) + 1):
for index in range(len(s) + 1 - size):
yield list(x[index:index + size])
list(groupme(x))
>>> [['A'], ['I'], ['R'], ['A', 'I'], ['I', 'R'], ['A', 'I', 'R']]
don't try to be so magical: two loops will do what you want; one over possible sequence starts, the inner over possible sequence lengths:
x = "AIR" # strings are iterables/sequences, too!
all_words = []
for begin in xrange(len(x)):
for length in xrange(1,len(x) - begin+1):
all_words.append(x[begin:begin+length])
using list comprehension:
letters=['A', 'I', 'R']
[letters[start:end+1]
for start in xrange(len(letters))
for end in xrange(start, len(letters))]
[['A'], ['A', 'I'], ['A', 'I', 'R'], ['I'], ['I', 'R'], ['R']]
if it is important to have the order you proposed (from longest to shortest and when the same length by starting position) you can do instead:
[letters[start:start+l+1]
for l in range(len(letters))[::-1]
for start in xrange(len(letters)-l)]
[['A', 'I', 'R'], ['A', 'I'], ['I', 'R'], ['A'], ['I'], ['R']]
Just to address Holroy comment. If instead of using list comprehension you use a generator expression (just substituting external [] with ()) you would get a much less memory requiring code. But in this case you must be careful of not using the result more than once or for instance not trying to use list methods (such as len, or removing elements) on the result.