Related
I'm solving the problem.
You have to leave the last list, but the previous list is printed out again.
def merge(xs,ys):
# xs, ys, ss = xs, ys, []
xs, ys, ss = xs[:], ys[:], []
while xs!=[] and ys!=[]:
if xs[0] <= ys[0]:
ss.append(xs[0])
xs.remove(xs[0])
else:
ss.append(ys[0])
ys.remove(ys[0])
ss.extend(xs)
ss.extend(ys)
return ss
accumulator = []
remain = []
def merge2R(xss):
if len(xss)% 2 != 0 :
OExcept = len(xss)-1
remain.append((xss[OExcept]))
xss.remove(xss[OExcept])
if xss != []:
accumulator.append(merge(xss[0],xss[1]))
xss.remove(xss[0])
xss.remove(xss[0])
return merge2R(xss)
else:
return accumulator + remain
The result comes out like this.
How can I fix it?
>>> merge2R([[2],[1,3],[4,6,7],[5,8],[9]])
[[1, 2, 3], [4, 5, 6, 7, 8], [1, 2, 3], [4, 5, 6, 7, 8], [9]]
Desired result value:
>>> merge2R([[2],[1,3],[4,6,7],[5,8]])
[[1,2,3], [4,5,6,7,8]]
>>> merge2R([[2],[1,3],[4,6,7],[5,8],[9]])
[[1,2,3], [4,5,6,7,8], [9]]
Your code was working, you just needed to reset accumulator and remain
def merge2R(xss):
# Declare use of globals
global remain
global accumulator
if len(xss) % 2 != 0:
OExcept = len(xss)-1
remain.append((xss[OExcept]))
xss.remove(xss[OExcept])
if xss != []:
accumulator.append(merge(xss[0], xss[1]))
xss.remove(xss[0])
xss.remove(xss[0])
return merge2R(xss)
else:
x = accumulator + remain
# Must reset accumulator and remain
accumulator = []
remain = []
return x
Because you initialise both arrays as empty, then append to them:
# Remain
remain.append((xss[OExcept]))
# Accumulator
accumulator.append(merge(xss[0], xss[1]))
After you have finished with the data in those arrays (at end of function) you need to discard it:
accumulator = []
remain = []
The result of not discarding these arrays is evident when calling the function with the same argument multiple times:
print(merge2R([[2], [1, 3]]))
print(merge2R([[2], [1, 3]]))
print(merge2R([[2], [1, 3]]))
print(merge2R([[2], [1, 3]]))
print(merge2R([[2], [1, 3]]))
[[1, 2, 3]]
[[1, 2, 3], [1, 2, 3]]
[[1, 2, 3], [1, 2, 3], [1, 2, 3]]
[[1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3]]
[[1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3]]
I am trying to find the intersection between a list and a list of lists. This is trivially solved with a simple for loop:
def find_intersec(x,y):
result = []
for i in range(len(y)):
if set(x).intersection(set(y[i])):
result.append(y[i])
return(result)
x = [1,2,3,4,5,6]
y = [[1,2,3], [4,5,6], [9,10,11]]
find_intersec(x,y)
How can I change the above into a numpy vectorization solution? I have tried numpy.intersect1d() with no success.
You can have a function like this:
import numpy as np
def find_intersec_vec(x, y):
y_all = np.concatenate(y)
y_all_in = np.isin(y_all, x)
splits = np.cumsum([0] + [len(lst) for lst in y])
y_in = np.logical_or.reduceat(y_all_in, splits[:-1])
return [lst for lst, isin in zip(y, y_in) if isin]
Test:
x = [1, 2, 3, 4, 5, 6]
y = [[1, 2, 3], [4, 5], [6, 7], [8, 9, 10, 11]]
print(find_intersec(x, y))
# [[1, 2, 3], [4, 5], [6, 7]]
print(find_intersec_vec(x, y))
# [[1, 2, 3], [4, 5], [6, 7]]
As you mentioned, numpy.intersect1d() can be used:
import numpy as np
x = [1,2,3,4,5,6]
y = [[1,2,3], [4,5,6], [9,10,11]]
intersec = [np.intersect1d(i, x) for i in y if len(np.intersect1d(i, x)) > 0]
result:
[array([1, 2, 3]), array([4, 5, 6])]
I want to get a list of values, by multiplication, like this:
[[1, 2, 3], [2, 4, 6], [3, 6, 9]]
So, I tried:
rGen = (i for i in range(1, 4))
matriz = [[x * y for y in rGen] for x in rGen]
And I get:
[[2, 3]]
How can I solve this?
Like this?
>>> r=range(1,4)
>>> [[x * y for x in r] for y in r]
[[1, 2, 3], [2, 4, 6], [3, 6, 9]]
The difference is how you use/assign the generator. As illustrated by this example (Python 2.x):
>>> r1=(i for i in range(1,4))
>>> r2=range(1,4)
>>> r3=[i for i in range(1,4)]
>>> r1
<generator object <genexpr> at 0x6ffffe1e4b0>
>>> r2
[1, 2, 3]
>>> r3
[1, 2, 3]
>>> [[x * y for x in r1] for y in r1]
[[2, 3]]
>>> [[x * y for x in r2] for y in r2]
[[1, 2, 3], [2, 4, 6], [3, 6, 9]]
>>> [[x * y for x in r3] for y in r3]
[[1, 2, 3], [2, 4, 6], [3, 6, 9]]
In the first example (r1), you get a generator object, which will only generate your sequence once, while in the other two examples you get lists, which you can use in a nested list comprehension (they will always evaluate to the same, no matter how many times you access them).
In Python 3.x, range() returns a different type, but the behavior is similar:
>>> r1=(i for i in range(1,4))
>>> r2=range(1,4)
>>> r3=[i for i in range(1,4)]
>>> r1
<generator object <genexpr> at 0x6ffffe7a518>
>>> r2
range(1, 4)
>>> r3
[1, 2, 3]
>>> [[x * y for x in r1] for y in r1]
[[2, 3]]
>>> [[x * y for x in r2] for y in r2]
[[1, 2, 3], [2, 4, 6], [3, 6, 9]]
>>> [[x * y for x in r3] for y in r3]
[[1, 2, 3], [2, 4, 6], [3, 6, 9]]
You are using the same generator (rGen) for both your outer and inner loop. What you should do is:
matrix = [[x * y for y in range(1,4)] for x in range(1,4)]
To return the product of elements of each list, you could do something like this,
>>> import operator
>>> from functools import reduce
>>> a = [[1, 2, 3], [2, 4, 6], [3, 6, 9]]
>>> [reduce(operator.mul, i, 1) for i in a]
[6, 48, 162]
>>>
I have two nested lists:
a = [[1, 1, 1], [1, 1, 1]]
b = [[2, 2, 2], [2, 2, 2]]
I want to make:
c = [[3, 3, 3], [3, 3, 3]]
I have been referencing the zip documentation, and researching other posts, but don't really understand how they work. Any help would be greatly appreciated!
You may use list comprehension with zip() as:
>>> a = [[1, 1, 1], [1, 1, 1]]
>>> b = [[2, 2, 2], [2, 2, 2]]
>>> [[i1+j1 for i1, j1 in zip(i,j)] for i, j in zip(a, b)]
[[3, 3, 3], [3, 3, 3]]
More generic way is to create a function as:
def my_sum(*nested_lists):
return [[sum(items) for items in zip(*zipped_list)] for zipped_list in zip(*nested_lists)]
which can accept any number of list. Sample run:
>>> a = [[1, 1, 1], [1, 1, 1]]
>>> b = [[2, 2, 2], [2, 2, 2]]
>>> c = [[3, 3, 3], [3, 3, 3]]
>>> my_sum(a, b, c)
[[6, 6, 6], [6, 6, 6]]
If you're going to do this a whole bunch, you'll be better off using numpy:
import numpy as np
a = [[1, 1, 1], [1, 1, 1]]
b = [[2, 2, 2], [2, 2, 2]]
aa = np.array(a)
bb = np.array(b)
c = aa + bb
Working with numpy arrays will be much more efficient than repeated uses of zip on lists. On top of that, numpy allows you to work with arrays much more expressively so the resulting code us usually much easier to read.
If you don't want the third party dependency, you'll need to do something a little different:
c = []
for a_sublist, b_sublist in zip(a, b):
c.append([a_sublist_item + b_sublist_item for a_sublist_item, b_sublist_item in zip(a_sublist, b_sublist)])
Hopefully the variable names make it clear enough what it going on here, but basically, each zip takes the inputs and combines them (one element from each input). We need 2 zips here -- the outermost zip pairs lists from a with lists from b whereas the inner zip pairs up individual elements from the sublists that were already paired.
I use python build-in function map() to do this.
If I have simple list a and b, I sum them as this way:
>>> a = [1,1,1]
>>> b = [2,2,2]
>>> map(lambda x, y: x + y, a, b)
[3, 3, 3]
If I have nested list a and b, I sum them as a similar way:
>>> a = [[1, 1, 1], [1, 1, 1]]
>>> b = [[2, 2, 2], [2, 2, 2]]
>>> map(lambda x, y: map(lambda i, j: i + j, x, y), a, b)
[[3, 3, 3], [3, 3, 3]]
Is there any version of split that works on generic list types? For example, in Haskell
Prelude> import Data.List.Split
Prelude Data.List.Split> splitWhen (==2) [1, 2, 3]
[[1],[3]]
Nope. But you can use itertools.groupby() to mimic it.
>>> [list(x[1]) for x in itertools.groupby([1, 2, 3], lambda x: x == 2) if not x[0]]
[[1], [3]]
One more solution:
output = [[]]
valueToSplit = 2
data = [1, 2, 3, 4, 1, 2, 3, 4, 5, 6, 2, 5, 2]
for i, val in enumerate(data):
if val == valueToSplit and i == len(data)-1:
break
output.append([]) if val == valueToSplit else output[-1].append(val)
print output # [[1], [3, 4, 1], [3, 4, 5, 6], [5]]
You can also create an iterator and use itertools.takewhile to include all matching items and discard the delimiter:
>>> import itertools
>>> l = [1, 2, 3]
>>> a = iter(l)
>>> [[_]+list(itertools.takewhile(lambda x: x!=2, a)) for _ in a]
[[1], [3]]
#TigerhawkT3 answer isn't flawlessly, but i can't add a comment
when l = [1, 2, 2, 2, 2, 3, 4]
output [[1], [2], [2, 3, 4]]
seem "wrong", but he inspired me
import itertools
l = [1, 2, 2, 2, 2, 3, 4]
a = iter(l)
output = [[_] + list(itertools.takewhile(lambda x: x != 2, a)) for _ in a if _ != 2]
output = [[1], [3, 4], [123, 123]]