How to multiply each element of two nested lists? - python

There are 2 nested lists, I want to multiply items at corresponding positions, so that the output is [[9, 16, 21], [24, 25, 24], [21, 16, 9]].
I use the program below. It works, but it seems too complex. Is that any quick way to do it? Is there any library to quickly perform such a task?
a = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
b = [[9, 8, 7], [6, 5, 4], [3, 2, 1]]
n = []
for i in range(3):
m = []
for j in range(3):
m.append(a[i][j] * b[i][j])
n.append(m)
print(n)

You can apply zip twice:
a=[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
b=[[9, 8, 7], [6, 5, 4], [3, 2, 1]]
result = [[j*k for j, k in zip(c, d)] for c, d in zip(a, b)]
Output:
[[9, 16, 21], [24, 25, 24], [21, 16, 9]]

You can map the lists to the multiplication operator:
from functools import partial
from operator import mul
print(list(map(list, map(partial(map, mul), a, b))))
Output:
[[9, 16, 21], [24, 25, 24], [21, 16, 9]]
If you're using Python 2.x you can skip the conversion to lists as well:
print map(partial(map, mul), a, b)

Related

How to delete multiple columns from a list of lists

test_list = [[4, 5, 6, 8],
[2, 7, 10, 9],
[12, 16, 18, 20]]
If I want to remove column 2, that is [5,7,16] from the list, I know I can use:
[j.pop(1) for j in test_list]
however, if I want to move 2 columns at the same time, that is [5,7,16] and [8,9,20], how can I change the code, so the result is:
The modified mesh after column deletion : [[4, 6], [2, 10], [12, 18]]
Here's one other way:
columns_to_remove = (1,3)
new_object = [[x for i,x in enumerate(l) if i not in columns_to_remove] for l in test_list]
Note that this creates a new object without modifying the original test_list.
test_list = [[4, 5, 6, 8], [2, 7, 10, 9],[12, 16, 18, 20]]
removeIndex = [1,3] # The indices you want to remove
for l in test_list:
for i,v in enumerate(removeIndex):
l.pop(v-i)
print(test_list)
You can try list comprehension with required indices
NOTE: I am not altering the original list, it is creating brand new list
test_list = [[4, 5, 6, 8],
[2, 7, 10, 9],
[12, 16, 18, 20]]
[[i[0], i[2]] for i in test_list]
[[4, 6], [2, 10], [12, 18]]
You can delete multiple columns using a numpy array. Please look at numpy.delete() for documentation.
import numpy as np
test_list = [[4, 5, 6, 8],
[2, 7, 10, 9],
[12, 16, 18, 20]]
a = np.array(test_list)
a = np.delete(a, [1, 3], axis=1)
print (a)
The output will be:
[[ 4 6]
[ 2 10]
[12 18]]
You can also use numpy.delete with slice() if you want to remove a column or a set of columns.
If you want to remove 2nd and 3rd column, you can give:
np.delete(a, slice(1, 3), axis=1)
array([[ 4, 8],
[ 2, 9],
[12, 20]])
If you want to delete 2 and 4th column, you can use slice(start, stop, skip) option as follows:
np.delete(a, slice(1, None,2), 1)
Output of this will be:
array([[ 4, 6],
[ 2, 10],
[12, 18]])
If you want the numpy array to be stored back as a regular list of list, you can always do a.tolist()
You can do it easily with numpy:
import numpy as np
test_list = [[4, 5, 6, 8],
[2, 7, 10, 9],
[12, 16, 18, 20]]
a = np.array(test_list)
a = np.delete(a, [1,3], axis=1)
print(a)
#output:
[[ 4 6]
[ 2 10]
[12 18]]

Concatenate arrays by column in python

I have a list of arrays, where each array is a list of lists. I want to turn this into a single array with all the columns. I've tried using for loops to get this done, but it feels like it should be doable in list comprehension. Is there a nice one-liner that will do this?
Example Input: [[[1,2],[3,4],[5,6]],[[7,8],[9,10],[11,12]]]
Desired Output: [[1,2,7,8],[3,4,9,10],[5,6,11,12]]
Note: Example only has two arrays in the main list, but my actual data has much more, so I'm looking for something that works for N subarrays.
Edit:
Example trying to solve this
Works for two but doesn't generalize:
[input[0][i]+input[1][i] for i in range(len(input[0]))]
These don't work, but show the idea:
[[element for table in input for element in row] for row in table]
[[*imput[j][i] for j in range(len(input))] for i in range(len(input[0]))]
Edit: Selected answer that uses only list comprehension and zip, but all answers (as of now) work, so use whichever fits your style/use case best.
You can generalize this from the standard list flattening pattern and zip:
>>> L = [[[1,2],[3,4],[5,6]],[[7,8],[9,10],[11,12]]]
>>> list([y for z in x for y in z] for x in zip(*L))
[[1, 2, 7, 8], [3, 4, 9, 10], [5, 6, 11, 12]]
>>> L = [[[1,2],[3,4],[5,6]],[[7,8],[9,10],[11,12]],[[13,14],[15,16],[17,18]]]
>>> list([y for z in x for y in z] for x in zip(*L))
[[1, 2, 7, 8, 13, 14], [3, 4, 9, 10, 15, 16], [5, 6, 11, 12, 17, 18]]
Here is one way of doing it:
initial = [[[1,2],[3,4],[5,6]],[[7,8],[9,10],[11,12]]]
output = [a+b for a, b in zip(*initial)]
print(output)
If you have more lists, this also works:
import itertools
initial = [[[1,2],[3,4],[5,6]],[[7,8],[9,10],[11,12]],[[13,14],[15,16],[17,18]]]
output = [list(itertools.chain.from_iterable(values)) for values in zip(*initial)]
print(output)
If you don't mind it is a tuple in the list.You could also try:
from itertools import chain
a = [[[1, 2], [3, 4], [5, 6]], [[7, 8], [9, 10], [11, 12]], [[13, 14], [15, 16], [17, 18]]]
output = list(map(list, map(chain.from_iterable, zip(*a))))
# [[1, 2, 7, 8, 13, 14], [3, 4, 9, 10, 15, 16], [5, 6, 11, 12, 17, 18]]
This would do it, I named your input first:
[*map(lambda x: list(i for s in x for i in s), zip(*first))]
[[1, 2, 7, 8], [3, 4, 9, 10], [5, 6, 11, 12]]

Remove smaller list with common items in a list of lists

I have a list of lists like this:
[[1, 2], [2, 4, 6], [6, 9], [9, 10, 11], [11, 20], [20, 25, 30]]
I want to remove from this the smaller lists that have the same items bigger lists. For example, the result for the above list should be:
[[2, 4, 6], [9, 10, 11], [20, 25, 30]]
Since [1, 2] and [2, 4, 6] has the common item 2, and
len([2, 4, 6]) > len([1, 2])
I can't think of a way to do this without horrible nested for-loops. Thanks!
You could do something like this:
data = [[1, 2], [2, 4, 6], [6, 9], [9, 10, 11], [11, 20], [20, 25, 30]]
result = []
for e in sorted(data, key=len, reverse=True):
if not any(set(e).intersection(prev) for prev in result):
result.append(e)
print(result)
Output
[[2, 4, 6], [9, 10, 11], [20, 25, 30]]

python oneline to create matrix of given order

I am looking for python oneliner that will create matrix with the given order and fill values from 1 to n. n = r X c
I achieved till this,
Matrix1 = [[x+1 for x in range(rowCount)] for x in range(columnCount)]
print Matrix1
But the output is
[[1, 2, 3], [1, 2, 3], [1, 2, 3]]
>>> matrix1 = [[1+x+y*rowCount for x in range(rowCount)] for y in range(columnCount)]
>>> matrix1
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
No, the correct way is without loop (and in one line):
import numpy as np
rowCount = 2
colCount = 5
np.array(range(1, 1+rowCount*colCount)).reshape(rowCount,colCount)
#array([[ 1, 2, 3, 4, 5],
# [ 6, 7, 8, 9, 10]])
You use the same variable for your two loops. Try this :
matrix1 = [[y*rowCount + x + 1 for x in range(rowCount)] for y in range(columnCount)]
print matrix1
Given c (column count), n, here's what I came up with:
[range(0, n)[cx:cx+c] for cx in range(0, n, c)]
Result:
In [16]: n = 9
In [17]: c = 3
In [18]: [range(0, n)[cx:cx+c] for cx in range(0, n, c)]
Out[18]: [[0, 1, 2], [3, 4, 5], [6, 7, 8]]
EDIT: More examples for non square matrices:
(mod is a function i created to quickly change r and c values, and calculate n from them)
In [23]: mod(8, 2) # 8 rows, 2 columns
In [24]: [range(0, n)[cx:cx+c] for cx in range(0, n, c)]
Out[24]: [[0, 1], [2, 3], [4, 5], [6, 7], [8, 9], [10, 11], [12, 13], [14, 15]]
In [25]: mod(3, 6) # 3 rows, 6 columns
In [26]: [range(0, n)[cx:cx+c] for cx in range(0, n, c)]
Out[26]: [[0, 1, 2, 3, 4, 5], [6, 7, 8, 9, 10, 11], [12, 13, 14, 15, 16, 17]]
In [27]: mod(10, 3) # 10 rows, 3 columns
In [28]: [range(0, n)[cx:cx+c] for cx in range(0, n, c)]
Out[28]:
[[0, 1, 2],
[3, 4, 5],
[6, 7, 8],
[9, 10, 11],
[12, 13, 14],
[15, 16, 17],
[18, 19, 20],
[21, 22, 23],
[24, 25, 26],
[27, 28, 29]]
It works for them too.

Splitting list based on missing numbers in a sequence

I am looking for the most pythonic way of splitting a list of numbers into smaller lists based on a number missing in the sequence. For example, if the initial list was:
seq1 = [1, 2, 3, 4, 6, 7, 8, 9, 10]
the function would yield:
[[1, 2, 3, 4], [6, 7, 8, 9, 10]]
or
seq2 = [1, 2, 4, 5, 6, 8, 9, 10]
would result in:
[[1, 2], [4, 5, 6], [8, 9, 10]]
Python 3 version of the code from the old Python documentation:
>>> # Find runs of consecutive numbers using groupby. The key to the solution
>>> # is differencing with a range so that consecutive numbers all appear in
>>> # same group.
>>> from itertools import groupby
>>> from operator import itemgetter
>>> data = [ 1, 4,5,6, 10, 15,16,17,18, 22, 25,26,27,28]
>>> for k, g in groupby(enumerate(data), lambda i_x: i_x[0] - i_x[1]):
... print(list(map(itemgetter(1), g)))
...
[1]
[4, 5, 6]
[10]
[15, 16, 17, 18]
[22]
[25, 26, 27, 28]
The groupby function from the itertools module generates a break every time the key function changes its return value. The trick is that the return value is the number in the list minus the position of the element in the list. This difference changes when there is a gap in the numbers.
The itemgetter function is from the operator module, you'll have to import this and the itertools module for this example to work.
Alternatively, as a list comprehension:
>>> [map(itemgetter(1), g) for k, g in groupby(enumerate(seq2), lambda i_x: i_x[0] - i_x[1])]
[[1, 2], [4, 5, 6], [8, 9, 10]]
This is a solution that works in Python 3 (based on previous answers that work in python 2 only).
>>> from operator import itemgetter
>>> from itertools import *
>>> groups = []
>>> for k, g in groupby(enumerate(seq2), lambda x: x[0]-x[1]):
>>> groups.append(list(map(itemgetter(1), g)))
...
>>> print(groups)
[[1, 2], [4, 5, 6], [8, 9, 10]]
or as a list comprehension
>>> [list(map(itemgetter(1), g)) for k, g in groupby(enumerate(seq2), lambda x: x[0]-x[1])]
[[1, 2], [4, 5, 6], [8, 9, 10]]
Changes were needed because
Removal of tuple parameter unpacking PEP 3113
map returning an iterator instead of a list
Another option which doesn't need itertools etc.:
>>> data = [1, 4, 5, 6, 10, 15, 16, 17, 18, 22, 25, 26, 27, 28]
>>> spl = [0]+[i for i in range(1,len(data)) if data[i]-data[i-1]>1]+[None]
>>> [data[b:e] for (b, e) in [(spl[i-1],spl[i]) for i in range(1,len(spl))]]
... [[1], [4, 5, 6], [10], [15, 16, 17, 18], [22], [25, 26, 27, 28]]
I like this one better because it doesn't require any extra libraries or special treatment for first case:
a = [1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 15, 16, 17, 18, 20, 21, 22]
b = []
subList = []
prev_n = -1
for n in a:
if prev_n+1 != n: # end of previous subList and beginning of next
if subList: # if subList already has elements
b.append(subList)
subList = []
subList.append(n)
prev_n = n
if subList:
b.append(subList)
print a
print b
Output:
[1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 15, 16, 17, 18, 20, 21, 22]
[[1, 2, 3, 4, 5, 6, 7, 8], [10, 11, 12], [15, 16, 17, 18], [20, 21, 22]]
My way
alist = [1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 15, 16, 17, 18, 20, 21, 22]
newlist = []
start = 0
end = 0
for index,value in enumerate(alist):
if index < len(alist)-1:
if alist[index+1]> value+1:
end = index +1
newlist.append(alist[start:end])
start = end
else:
newlist.append(alist[start: len(alist)])
print(newlist)
Result
[[1, 2, 3, 4, 5, 6, 7, 8], [10, 11, 12], [15, 16, 17, 18], [20, 21, 22]]

Categories

Resources