How to properly add elements to an array in Python - python

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.

Related

Difference between using list.reverse and list = list[::-1] in python

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

How to get those elements which are at the same position in two 2D matrix in Python using a filter?

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]

How to add elements in a 2D array in Python [duplicate]

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)

How can I get a set of (possibly overlapping) slices in a Python list based on elements that match a criteria?

Suppose I have a python list l=[1,2,3,4,5]. I would like to find all x-element lists starting with elements that satisfy a function f(e), or the sublist going to the end of l if there aren't enough items. For instance, suppose f(e) is e%2==0, and x=3 I'd like to get [[2,3,4],[4,5]].
Is there an elegant or "pythonic" way to do this?
>>> f = lambda e: e % 2 == 0
>>> x = 3
>>> l = [1, 2, 3, 4, 5]
>>> def makeSublists(lst, length, f):
for i in range(len(lst)):
if f(lst[i]):
yield lst[i:i+length]
>>> list(makeSublists(l, x, f))
[[2, 3, 4], [4, 5]]
>>> list(makeSublists(list(range(10)), 5, f))
[[0, 1, 2, 3, 4], [2, 3, 4, 5, 6], [4, 5, 6, 7, 8], [6, 7, 8, 9], [8, 9]]
Using a list comprehension:
>>> l = range(1,6)
>>> x = 3
>>> def f(e):
return e%2 == 0
>>> [l[i:i+x] for i, j in enumerate(l) if f(j)]
[[2, 3, 4], [4, 5]]

Generator to Yield a List

I have three lists of lists, and I'm trying to write a generator function to help me package up values in the same index.
So my lists:
list1 = [[1, 2, 3], [2, 3, 4],...]
list2 = [[4, 5, 6], [5, 6, 7],...]
list3 = [[8, 9, 10], [9, 10, 11],...]
My desired output:
result1 = [[1, 4, 8], [2, 5, 9],...]
result2 = [[2, 5, 9], [3, 6, 10],...]
result3 = [[3, 6, 10], [4, 7, 11],...]
My attempt:
def bundle(x, y, z, index):
for row in x, y, z:
for item in row[index]:
yield list(item)
I keep getting float is not iterable errors. If i modify it slightly:
def bundle(x, y, z, index):
for row in x, y, z:
for item in row:
yield item[index]
I get the values I want as one large sequence, but I would prefer to keep them grouped in a nested style.
If you're dealing with large lists, a custom, fully lazy approach would be the following:
import itertools as it
def bundle(lists, index):
return ([b[index] for b in blocks] for blocks in it.izip(*lists))
print list(bundle([[[1, 2, 3], [2, 3, 4]],
[[4, 5, 6], [5, 6, 7]],
[[8, 9, 10], [9, 10, 11]]],
0))
# => [[1, 4, 8], [2, 5, 9]]
One way to do this is by a repeated application of zip():
res1, res2, res3 = zip(*(zip(*x) for x in zip(list1, list2, list3)))
This uses zip(list1, list2, list3) to create a sequence of matrices, zip(*x) to transpose each of this matrices, and a final zip() to unpack to the three resulting sequences. (I don't think this approach is very efficient.)
If you're dealing with numeric values then you could use numpy's transposition method to achieve what you want:
import numpy
numpy.array([list1,list2, list3]).T

Categories

Resources