This question already has answers here:
Add two matrices in python
(4 answers)
Closed 2 months ago.
To be honest, i don't really know how to properly explain what i want, so i better show it.
Basically what i want to do is add elements from 2 different 2D lists
a = [[5, 4, 5, 4], [4, 5, 6, 8]]
b = [[1, 2, 4, 5], [5, 6, 6, 2]]
And i wan't to merge them in a 2D array named c, so it should look something like this:
c = [[6, 6, 9, 9], [9, 11, 12, 10]]
I looked around, but sum and zip functions didn't give me the desired output. Thanks in advance for any help
A simple list comprehension and zip will be sufficient, Use:
c = [[x + y for x, y in zip(s1, s2)] for s1, s2 in zip(a, b)]
Result:
#print(c)
[[6, 6, 9, 9], [9, 11, 12, 10]]
What you are seeking is essentially matrix addition:
import numpy as np
a = np.array([[5, 4, 5, 4], [4, 5, 6, 8]])
b = np.array([[1, 2, 4, 5], [5, 6, 6, 2]])
c = a + b
Where "array" is numpy's vector and matrix object, so when you return "c", you should see
>>> c
array ([[6, 6, 9, 9],
[9, 11, 12, 10]])
In fact I could do this by using two zip functions, one inside another.
c = []
for x, y in zip(a, b):
array = []
for e1, e2 in zip(x, y):
array.append(e1+e2)
c.append(array)
print(c)
The output would be:
[[6, 6, 9, 9], [9, 11, 12, 10]]
Since you need the result in a new array, I'm creating a new matrix C as a copy of A.
So that i can easily add B to A.
You can do this:
c = a
for i in range(0,len(a)):
for j in range(0,len(a[0]):
c[i][j] = a[i][j] + b[i][j]
print(c)
You can use for loop to merge 2 arrays.
c = [[a[i][j] + b[i][j] for j in range(len(a[0]))] for i in range(len(a))]
You can use a nested loop to solve the problem.
a = [[5, 4, 5, 4], [4, 5, 6, 8]]
b = [[1, 2, 4, 5], [5, 6, 6, 2]]
c=[]
l=len(a)
for i in range(l):
temp=[]
l2=len(a[i])
for j in range(l2):
p=a[i][j]+b[i][j]
temp.append(p)
c.append(temp)
print(c)
You can use a loop for this.
from builtins import len
def insaneSum(x,y):
newTable = x #creates a copie of your first array
i = 0
j = 0
while i < len(x):
while j < len(x[i]):
newTable[i][j] = x[i][j] + y[i][j] #replaces value of copie for the sum
j = j+1
i = i+1
return newTable
a = [[5, 4, 5, 4], [4, 5, 6, 8]]
b = [[1, 2, 4, 5], [5, 6, 6, 2]]
c = insaneSum(a,b)
print(c)
Related
I want to extract range of columns. I know how to do that in numpy but I don't want to use numpy slicing operator.
import numpy as np
a = [[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]]
arr = np.array(a)
k = 0
print(arr[k:, k+1]) # --> [2 7]
print([[a[r][n+1] for n in range(0,k+1)] for r in range(k,len(a))][0]) # --> [2]
What's wrong with second statement?
You're overcomplicating it. Get the rows with a[k:], then get a cell with row[k+1].
>>> [row[k+1] for row in a[k:]]
[2, 7]
a = [[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]]
k = 0
print(list(list(zip(*a[k:]))[k+1])) # [2, 7]
Is this what you're looking for?
cols = [1,2,3] # extract middle 3 columns
cols123 = [[l[col] for col in cols] for l in a]
# [[2, 3, 4], [7, 8, 9]]
I'm writing an algorithm that rotates a square matrix 90ยบ degrees in-place, without using a second matrix. It works, but I've got one small problem that is troubling me.
So the basic, working algorithm is:
def rotate(matrix):
n = len(matrix)
# reverse rows
matrix.reverse()
# reflect
start = 0
for row in range(n):
for col in range(start, n):
matrix[row][col], matrix[col][row] = matrix[col][row], matrix[row][col]
start = start + 1
The idea is to pass a matrix defined as a list of lists, like [[1, 2, 3], [4, 5, 6], [7, 8, 9]].
Example input/output:
>>> some_matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> rotate(some_matrix)
>>> print(some_matrix)
[[7, 4, 1], [8, 5, 2], [9, 6, 3]]
Great. So, I was wondering if I could replace matrix.reverse() with something maybe a little more intuitive, like simply using slice indexing. So I wrote a new rotate, like this:
def rotate2(matrix):
n = len(matrix)
# reverse rows
matrix = matrix[::-1]
# reflect
start = 0
for row in range(n):
for col in range(start, n):
matrix[row][col], matrix[col][row] = matrix[col][row], matrix[row][col]
start = start + 1
Which SHOULD give me the same results, based on:
>>> a = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> b = a
>>> b = b[::-1]
>>> a.reverse()
>>> print(a)
[[7, 8, 9], [4, 5, 6], [1, 2, 3]]
>>> print(b)
[[7, 8, 9], [4, 5, 6], [1, 2, 3]]
>>> print(a==b)
True
However, when I use rotate2 on the same input/output example, I get:
>>> some_matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> rotate2(some_matrix)
>>> print(some_matrix)
[[9, 6, 3], [8, 5, 2], [7, 4, 1]]
So what am I missing here?
matrix = matrix[::-1] creates a new list and assigns it to the local name matrix; it does not modify the original list in-place.
matrix.reverse(), on the other hand, does modify the original list.
Consider these simple functions:
def r1(m):
m = m[::-1]
def r2(m):
m.reverse()
>>> x = [[1,2], [3,4]]
>>> r1()
>>> x
[[1,2], [3,4]]
>>> r2()
>>> x
[[3,4],[1,2]]
I am trying to get the elements as a list if any of them in the same position in two 2D matrices.
Let's consider matrix A and matrix B
A = [[1, 2, 3],[4, 5, 6],[7, 8, 9]]
B = [[0, 2, 5],[6, 2, 4],[7, 8, 1]]
The resultant list should be
C = [2, 7, 8]
I have tried using a filter but it is not working.
def find(A):
for i in range(3):
for j in range(3):
if A[i][j] == B[i][j]:
return A[i][j]
else:
return False
A = [[1, 2, 3],[4, 5, 6], [7, 8, 9]]
B = [[0, 2, 5],[6, 2, 4], [7, 8, 1]]
C = filter(find, A)
for element in C:
print(element)
Note: Please use a filter to achieve the target.
Solution using filter:
def find(L):
A, B = L
if A == B:
return True
else:
return False
A = [[1, 2, 3],[4, 5, 6], [7, 8, 9]]
B = [[0, 2, 5],[6, 2, 4], [7, 8, 1]]
# flatten lists
A = [item for row in A for item in row]
B = [item for row in B for item in row]
C = filter(find, zip(A,B))
# filter returns a tuple for each row but we only want the single element
C = [item[0] for item in C]
print(list(C))
Gives us
[2, 7, 8]
Try this,
def func(t):
return True if t[0] == t[1] else False
A = [[1, 2, 3],[4, 5, 6],[7, 8, 9]]
B = [[0, 2, 5],[6, 2, 4],[7, 8, 1]]
C = [item1 for lst1, lst2 in zip(A, B) for item1, item2 in filter(func, zip(lst1, lst2))]
>>> C
[2, 7, 8]
Basic Answer
First we loop over A and B, i and z now holds the inner lists.
Then we loop over those inner lists using g and q, if they are equal, we append them to the empty list.
to_fill = []
for i,z in zip(A,B):
for g,q in zip(i,z):
if g==q:
to_fill.append(g)
Adapt it as you please.
The most efficient way of achieving what you want is by using numpy:
import numpy as np
A = np.asarray(A)
B = np.asarray(B)
C = A[A==B]
I have two arrays as the code shows below (A and B). I would like to take as output C = [[1, 2, 3, 11], [4, 5, 6, 12], [7, 8, 9, 13]]
I'm trying to, but the only thing I could reach was this:
A = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
B = [11, 12, 13]
C = [[x, y] for x, y in zip(A, B)]
print(C)
# Output: [[[1, 2, 3], 11], [[4, 5, 6], 12], [[7, 8, 9], 13]]
You just need to make an array of a single element (y) and then add the two lists together
[x + [y] for x, y in zip(A, B)]
If it doesn't need to be a new list and modifying A suffices:
for a, b in zip(A, B):
a.append(b)
It's more efficient, at least for longer inner lists.
You didn't have the same level of nesting in both A and B, which is why you got a weird answer. A is a list of lists, while B is just a list.
Solutions
If you want to add inplace:
A.append(B)
# Output: A = [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]
Otherwise:
C = A + [B]
which leaves A and B untouched and creates a new joined list.
Timings
Conclusion: for this problem it really doesn't matter which way you do it, as the timings are about the same for each case. Some ways are more readable though.
Code for timing:
import timeit
A = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
B = [10, 11, 12]
def append_arrs(arrs=(A, B)):
a, b = arrs
a.append(b)
return a
def plus_arrs(arrs=(A, B)):
return arrs[0] + [arrs[1]]
def loopadd_arrs(arrs=(A, B)):
return [x + [y] for x, y in zip(*arrs)]
def listadd_arrs(arrs=(A, B)):
a, b = arrs
return list((*a, b))
func_list = ["append_arrs", "plus_arrs", "loopadd_arrs", "listadd_arrs"]
for func in func_list:
t = timeit.timeit(stmt=f'{func}', setup=f'from __main__ import {func}')
print(f"Time for {func}: {t}")
Possible with numpy
import numpy as np
A = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
B = np.array([[11, 12, 13]]).T
C = np.append(A,B,axis=1)
Possibly you will have to transpose C according to the shape you want.
I have an array a = [[1,2,3,4,5,6,7,8,9,10],[4,1,6,2,3,5,8,9,7,10]], where lets say a1 = [1,2,3,4,5,6,7,8,9,10] and a2 = [4,1,6,2,3,5,8,9,7,10], from which I have constructed cyclic permutation. Note that a1 is a sorted array. For e.g in my case, the cycles are;
c = [[4, 2, 1], [6, 5, 3], [8, 9, 7], [10]]
lets say c1 = [4, 2, 1]
c2 = [6, 5, 3]
c3 = [8, 9, 7]
c4 = [10]
Now I want to form new arrays a11 and a22 as follow;
I have a method that gives all the cycle in a given permutation, but constructing new arrays from it, seems to be complicated. Any ideas to implement this is in python3 would be much appreciated.
-------------------
To obtain cycles;
import numpy as np
import random
def cx(individual):
c = {i+1: individual[i] for i in range(len(individual))}
cycles = []
while c:
elem0 = next(iter(c)) # arbitrary starting element
this_elem = c[elem0]
next_item = c[this_elem]
cycle = []
while True:
cycle.append(this_elem)
del c[this_elem]
this_elem = next_item
if next_item in c:
next_item = c[next_item]
else:
break
cycles.append(cycle)
return cycles
aa = cx([4,1,6,2,3,5, 8,9,7,10])
print("array: ", aa)
You can ues itertools.permutations to get different permutations of items of a, then use itertools.cycle to cycle through dicts that map items of sublists of a to their indices, and zip the sublists of c with the mappings to produce sequences that follow the indices specified by the cycling dicts:
a = [[1,2,3,4,5,6,7,8,9,10],[4,1,6,2,3,5,8,9,7,10]]
c = [[4, 2, 1], [6, 5, 3], [8, 9, 7], [10]]
from itertools import cycle, permutations
print([[d[i] for i in range(len(d))] for l in permutations(a) for d in ({p[n]: n for s, p in zip(c, cycle({n: i for i, n in enumerate(s)} for s in l)) for n in s},)])
This outputs:
[[1, 2, 6, 4, 3, 5, 7, 8, 9, 10], [4, 1, 3, 2, 5, 6, 8, 9, 7, 10]]