Python copy matrix - python

So i have a quick question my code is supposed to delete the row and column (from i and j) which it does but for some reason it also changes the original matrix (while i have copied it). Can someone tell me why that is?
def reduce_matrix(M, i, j):
newM=list(M[:])
for q in range(len(newM)+1):
if q==i-1:
del newM[q]
for y in range(len(newM)):
for x in range(len(newM[y])):
if x==j-1:
del newM[y][x]
return newM

You have to copy all sublists in a list, instead of copy all list.
try this:
def reduce_matrix(M, i, j):
newM=[k[:] for k in M]
#rest of code
From your program:. Try to print id of each sublists.
def reduce_matrix(M, i, j):
newM=list(M[:])
print id(M[0]), id(M[1]), id(M[2])
for q in range(len(newM)+1):
if q==i-1:
del newM[q]
for y in range(len(newM)):
for x in range(len(newM[y])):
if x==j-1:
del newM[y][x]
return newM
lis = [[1,2,3],[3,4,5],[7,4,2]]
print id(lis[0]), id(lis[1]), id(lis[2])
reduce_matrix(lis, 1, 1)
>>>
3074546604 3072046316 3072047084
3074546604 3072046316 3072047084
That proves that, sublists are just tagging or pointing to another variable.So modification for any sublist will happen to every sublist with same tags.
For example:
a = [1,2]
b = a
c = a
b.append(3)
print a
print b
print c
>>>
[1, 2, 3]
[1, 2, 3]
[1, 2, 3]
Hope this helps.

you only copy the first list, not the sublist.
if you want to return a new matrix with reduce row and column, you can do this:
def reduce_matrix(M, i, j):
return [[M[m][n] for n in range(len(M[m])) if j-1 != n ] \
for m in range(len(M)) if i-1 != m]

Related

iterating using args to create multiple buttons with tkinter using a button as a list - list assignment index out of range [duplicate]

I tried writing some code like:
i = [1, 2, 3, 5, 8, 13]
j = []
k = 0
for l in i:
j[k] = l
k += 1
But I get an error message that says IndexError: list assignment index out of range, referring to the j[k] = l line of code. Why does this occur? How can I fix it?
j is an empty list, but you're attempting to write to element [0] in the first iteration, which doesn't exist yet.
Try the following instead, to add a new element to the end of the list:
for l in i:
j.append(l)
Of course, you'd never do this in practice if all you wanted to do was to copy an existing list. You'd just do:
j = list(i)
Alternatively, if you wanted to use the Python list like an array in other languages, then you could pre-create a list with its elements set to a null value (None in the example below), and later, overwrite the values in specific positions:
i = [1, 2, 3, 5, 8, 13]
j = [None] * len(i)
#j == [None, None, None, None, None, None]
k = 0
for l in i:
j[k] = l
k += 1
The thing to realise is that a list object will not allow you to assign a value to an index that doesn't exist.
Your other option is to initialize j:
j = [None] * len(i)
Do j.append(l) instead of j[k] = l and avoid k at all.
You could also use a list comprehension:
j = [l for l in i]
or make a copy of it using the statement:
j = i[:]
j.append(l)
Also avoid using lower-case "L's" because it is easy for them to be confused with 1's
I think the Python method insert is what you're looking for:
Inserts element x at position i.
list.insert(i,x)
array = [1,2,3,4,5]
# array.insert(index, element)
array.insert(1,20)
print(array)
# prints [1,20,2,3,4,5]
You could use a dictionary (similar to an associative array) for j
i = [1, 2, 3, 5, 8, 13]
j = {} #initiate as dictionary
k = 0
for l in i:
j[k] = l
k += 1
print(j)
will print :
{0: 1, 1: 2, 2: 3, 3: 5, 4: 8, 5: 13}
One more way:
j=i[0]
for k in range(1,len(i)):
j = numpy.vstack([j,i[k]])
In this case j will be a numpy array
Maybe you need extend()
i=[1,3,5,7]
j=[]
j.extend(i)

Pythonic popping from a list to another list

I have two lists
a = [1,2,3]
b = []
I want to move an element from list a, if it meets a certain condition.
a = [1,3]
b = [2]
The below code shows an example, however, I would like to do this inside of a single loop. How do I do this more efficiently?
a = [1,2,3]
b = []
pop_list = []
for i in range(len(a)):
if a[i] == 2:
print("pop:", a[i])
pop_list.append(i)
for i in range(len(pop_list)):
b.append(a.pop(pop_list[i]))
# Reset pop_list
pop_list=[]
Ideally, I would not generate a new list b.
A pair of list comprehensions would do the job: one to select the desired elements for b, the other to remove them from a
b = [i for i in a if i == 2]
a = [i for i in a if i != 2]
You can use filter and itertools.filterfalse and use the same filtering function for both:
from itertools import filterfalse
a = [1,2,3]
b = []
list(filterfalse(lambda x: x == 2, a))
list(filter (lambda x: x == 2, a))
[1, 3]
[2]
Here is the itertools.filterfalse docs.
If the element x exists you could just remove it from b and append it to a.
a = [1, 2, 3]
b = []
x = 2
def remove_append(a, b, x):
if x in a:
a.remove(x)
b.append(x)
remove_append(a, b, x)
print(a)
print(b)
Output:
[1, 3]
[2]
We must pass through all elements, however, you can apply this trick to add to the appropriate list in one loop:
(Appending to a loop is more efficient than deleting an element at arbitrary position)
a = [1,2,3]
condition_false, condition_true = [], []
for v in a:
# Add to the right list
(condition_false, condition_true)[v == 2].append(v)
# [1, 3]
print(condition_false)
# [2]
print(condition_true)
Here is a single loop way that's similar to your initial method:
length = len(a)
popped = 0
for i in range(length):
if i == length - popped:
break
if a[i] == 2:
b.append(a.pop(i))
popped += 1
If we keep track of how many elements we pop from a, we can just stop our loop that many elements early since there are fewer elements left in a.

Entering a matrix using input [duplicate]

I tried writing some code like:
i = [1, 2, 3, 5, 8, 13]
j = []
k = 0
for l in i:
j[k] = l
k += 1
But I get an error message that says IndexError: list assignment index out of range, referring to the j[k] = l line of code. Why does this occur? How can I fix it?
j is an empty list, but you're attempting to write to element [0] in the first iteration, which doesn't exist yet.
Try the following instead, to add a new element to the end of the list:
for l in i:
j.append(l)
Of course, you'd never do this in practice if all you wanted to do was to copy an existing list. You'd just do:
j = list(i)
Alternatively, if you wanted to use the Python list like an array in other languages, then you could pre-create a list with its elements set to a null value (None in the example below), and later, overwrite the values in specific positions:
i = [1, 2, 3, 5, 8, 13]
j = [None] * len(i)
#j == [None, None, None, None, None, None]
k = 0
for l in i:
j[k] = l
k += 1
The thing to realise is that a list object will not allow you to assign a value to an index that doesn't exist.
Your other option is to initialize j:
j = [None] * len(i)
Do j.append(l) instead of j[k] = l and avoid k at all.
You could also use a list comprehension:
j = [l for l in i]
or make a copy of it using the statement:
j = i[:]
j.append(l)
Also avoid using lower-case "L's" because it is easy for them to be confused with 1's
I think the Python method insert is what you're looking for:
Inserts element x at position i.
list.insert(i,x)
array = [1,2,3,4,5]
# array.insert(index, element)
array.insert(1,20)
print(array)
# prints [1,20,2,3,4,5]
You could use a dictionary (similar to an associative array) for j
i = [1, 2, 3, 5, 8, 13]
j = {} #initiate as dictionary
k = 0
for l in i:
j[k] = l
k += 1
print(j)
will print :
{0: 1, 1: 2, 2: 3, 3: 5, 4: 8, 5: 13}
One more way:
j=i[0]
for k in range(1,len(i)):
j = numpy.vstack([j,i[k]])
In this case j will be a numpy array
Maybe you need extend()
i=[1,3,5,7]
j=[]
j.extend(i)

Python sorted list containing all integers in both consumed list

How would I go about writing a recursive function that consumes two lists and then produces a list with the elements that are in both lists? If both lists have a number twice in each, the produced list will also have that number in it twice.
This is what I have so far:
def merge(L1, L2, i, j, R):
if L1[i] == L2[j]:
R.append(L1[i])
R.append(L2[j])
merge(L1, L2, i, j+1, R)
else:
merge(L1, L2, i+1, j, R)
def sorted_intersection(lst1, lst2):
R = []
return merge(lst1, lst2, lst1[0], lst2[0], R)
Nvm, figured out the code. Thanks for all the help!
Please see the documentation of the module collections, which contains helpers for many functional tasks:
from collections import defaultdict, Counter
# Preserves the order of b:
def in_both(a, b):
# Count the occurrences of elements in a:
a = Counter(a)
# Default to 0:
a = defaultdict(lambda: 0, a)
# Return true if there is a positive amount of items x in a left:
def take_from_a(x):
cur = a[x]
if cur > 0:
a[x] = cur - 1
return True
# Filter out elements in b that are not often enough in b:
return filter(take_from_a, b)
in_both("abbcccdddd", "abcdabcde") == "abcdbcd"
In here a and b are both iterated once.
Why recursive?
a = [1, 2, 2, 3, 3]
b = [2, 3, 4]
result = [[x, b.remove(x)][0] for x in a if x in b]
result
[2, 3, 3]

Matrix Addition in Python - list

I'm trying to write Matrix Addition function using Python.
Here is the code I've been trying, but it gives me a list index error and I cannot figure out why.
def matrixADD(A,B):
Z = []
#TODO
for i in range(0,len(A)):
for column in range(0, len(A)):
result = A[i][column] + B[i][column]
Z[i][column] = (result)
return Z
using the following lists:
A = [[2,4], [7,0], [6,3]]
B = [[3,1], [-1,8], [-3, 3]]
So in theory, A[0][0] + B[0][0] would equal 5, and I would want to add that value to position Z[0][0].
However I keep receiving the error: IndexError: list index out of range
>>> A = [[2,4], [7,0], [6,3]]
>>> B = [[3,1], [-1,8], [-3, 3]]
>>> Z = [map(sum, zip(*t)) for t in zip(A, B)]
>>> Z
[[5, 5], [6, 8], [3, 6]]
As for how you could fix your current code:
Z = []
for i in range(len(A)):
row = []
for j in range(len(A[i])):
row.append(A[i][j] + B[i][j])
Z.append(row)
The important parts here being that you cannot just assign to Z[i][j] unless that row/column already exists, so you need to construct each inner list separately and append them to Z. Also the inner loop needs to end at the length of a row, so I changed range(len(A)) to range(len(A[i])).
len(A) = 3 but you matrix have dimension 3x2 so when you try to access A[2][2] (because column is between 0 and len(A)) you are out of bounds.
For column you are using range 0 to len(A) (which is 3). A[i][2] will be out of range, because A[i]'s length is only 2.
Try using column range to end a len(A[i]) instead of len(A):
def matrixADD(A,B):
Z = []
#TODO
for i in range(0,len(A)):
for column in range(0, len(A[i])):
result = A[i][column] + B[i][column]
Z[i][j] = (result)
return Z

Categories

Resources