Python: Get set of values, by multiplication - python

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]
>>>

Related

Numpy vectorization: Find intersection between list and list of lists

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])]

Is there a way to combine a list like this?

assume that a and b are list.
a = [[1], [2]]
b = [[5, 6, 7], [3, 4, 5]]
I want to get a list which is
[[1,5,6,7], [2,3,4,5]]
Is there any way to do that effectively? Either lists or numpy array is OK.
zip is your friend:
>>> a = [[1], [2]]
>>> b = [[5, 6, 7], [3, 4, 5]]
>>> [x+y for x, y in zip(a, b)]
[[1, 5, 6, 7], [2, 3, 4, 5]]
You can also use map; the operator module provides a ready-made definition of lambda x,y: x + y for such uses.
>>> import operator
>>> list(map(operator.add, a, b))

Insert an array in an array using loop

I write the following code to create an array like [[1,2,3],[2,2,3],[3,2,3]],
def f(X):
X[0]=X[0]+1
return X
L=[]
X=[1,2,3]
for i in range(0,3):
L=L+[X]
X=f(X)
print(L)
But it is printing [[4, 2, 3], [4, 2, 3], [4, 2, 3]]. Why it is happening and how to solve this using the function 'f'?
Thanks
If you have to use your function f, then try as follows:
l = []
x = [1, 2, 3]
def f(x):
x[0] = x[0] + 1
return x
for i in range(3):
l.append(x[:])
x = f(x)
Output:
>>> l
[[1, 2, 3], [2, 2, 3], [3, 2, 3]]

How can I have references of lists in Python

Say I have two following lists.
x = [1, 2, 3]
y = [4, 5, 6]
Now I want a list that contains references to these lists,
So instead of wanting
z = [x, y] -> [[1, 2, 3], [4, 5, 6]]
I want the following
z = [ref of x, ref of y]
How can I achieve that in Python?
z = [x, y] is the way to use references:
>>> x = [1, 2, 3]
>>> y = [4, 5, 6]
>>> z = [x, y]
>>> x[0] = 0
>>> z
[[0, 2, 3], [4, 5, 6]]
If you want to copy, use the slice notation or the copy module:
>>> z=[x[:],y[:]]
>>> x[0] = 11
>>> x
[11, 2, 3]
>>> z
[[0, 2, 3], [4, 5, 6]]
z=[x,y] keeps the references, not the copies. This can be proved as:
>>> x = [1, 2, 3]
>>> y = [4, 5, 6]
>>> id(x),id(y)
(139643028466504, 139643028484320)
>>> z=[x,y]
>>> id(z[0]),id(z[1])
(139643028466504, 139643028484320)
As you can see addresses of x and y are similar to addresses z[0] and z[1], which clearly is the definition of reference.

concatenate lists in python

I have a 3x2 list called x and a 1x2 list called y:
x=[[1,2],[3,4],[5,6]]
and
y=[10,20]
my question is how to concatenate y to the end of x to end up with a 4x2 list like:
x=[[1,2],[3,4],[5,6],[10,20]]
I've tried this:
xx=[x,y]
but it gives me this which is not a 4x2 list:
xx=[[[1,2],[3,4],[5,6]],[10,20]]
>>> x = [[1, 2], [3, 4], [5, 6]]
>>> x
[[1, 2], [3, 4], [5, 6]]
>>> x.append([10, 20])
>>> x
[[1, 2], [3, 4], [5, 6], [10, 20]]
Or:
>>> x = [[1, 2], [3, 4], [5, 6]]
>>> x
[[1, 2], [3, 4], [5, 6]]
>>> x += [[10, 20]] # a list with a list as its only element
>>> x
[[1, 2], [3, 4], [5, 6], [10, 20]]
Given:
x = [[1,2],[3,4],[5,6]]
y = [10,20]
this:
x.append(y)
will give you:
[[1, 2], [3, 4], [5, 6], [10, 20]]
Note however that this modifies x.
If you don't want to modify x, this is another way:
xx = x + [y[:]]
setting xx to:
[[1, 2], [3, 4], [5, 6], [10, 20]]
We use y[:] rather than simply y in the above assignment because we want to create separate copy of y for xx so later, should (the original) y be modified it would not lead to changes in xx.
>>> x=[[1,2],[3,4],[5,6]]
>>> y=[10,20]
>>> x.append(y) # or x.append(list(y)) to append a shallow copy of y
>>> x
[[1, 2], [3, 4], [5, 6], [10, 20]]
If you want a new list:
z = x + [y]
Note, that using [y] makes the content a list within a list, so that this works.
If you want to modify x inplace, then:
x.append(y)
Although I don't use it often myself, I think it's worth mentioning the list's extend member function:
>>> x=[[1,2],[3,4],[5,6]]
>>> y=[10,20]
>>> x.extend([y])
>>> x
[[1, 2], [3, 4], [5, 6], [10, 20]]
http://docs.python.org/tutorial/datastructures.html#more-on-lists

Categories