Why does Python not manipulate this array? [duplicate] - python

This question already has answers here:
How to modify list entries during for loop?
(10 answers)
Closed 7 years ago.
I have the following code snippet:
d = [[0,558,437,142,45,290], [558,0,232,500,600,523], [437,232,0,408,492,572],
[142,500,408,0,180,197], [45,600,492,180,0,254], [290,523,572,197,254,0]]
for row in d:
for elem in row:
elem = elem * 2
print d[0][1]
print '\n'
Why does it not print the new value, it still prints 558

elem = elem * 2 modifies the value of a variable named elem. This variable has nothing to do with the list other than its initial value came from a list element.
To do what you want, you need indexes into the array. Alternatively, you can use the map() function. However, this will only create a new list with the new values rather than changing the values of the original list.

You are assigning a new value to the variable elem. This does not effect the list. Instead try this:
d = [[0,558,437,142,45,290], [558,0,232,500,600,523],
[437,232,0,408,492,572],
[142,500,408,0,180,197], [45,600,492,180,0,254], [290,523,572,197,254,0]]
for row in d:
for index in range(len(row)):
row[index] *= 2
print d[0][1]
print '\n'
Notice that I use index for the index to the element instead of accessing the element itself.

Aside of the "why" as mentionned in other answers, here is how you can achieve this using list comprehensions:
d = [[0,558,437,142,45,290], [558,0,232,500,600,523], [437,232,0,408,492,572],
[142,500,408,0,180,197], [45,600,492,180,0,254], [290,523,572,197,254,0]]
for i, el in enumerate(d):
d[i] = [row * 2 for row in el]
print(d)

You probably want something like this instead:
double_d = [[elem * 2 for elem in row] for row in d]
Using list comprehensions is more idiomatic Python.

Related

How to avoid index out of range error with current implementation? [duplicate]

This question already has answers here:
How to remove items from a list while iterating?
(25 answers)
Closed last year.
I've been given a list of integers called nums, and am trying to remove all occurrences of the value (val). I'm trying to see where val matches an index of nums and am trying to remove it from the list. However, I keep getting a "list index out of range" error. I'm guessing it is because as I am popping the element of nums that matches val, it shrinks the list so it goes out of range. Is it not possible to remove all occurrences of value in this way?
nums = [3,2,2,3]
val = 2
for i in range(len(nums)):
if val == nums[i]:
nums.pop(i)
print(nums)
You should not try to remove elements from the list as you're iterating over it, as the memory is shifting as you're accessing it.
Instead, you should create a new list:
nums = [3,2,2,3]
val = 2
print([num for num in nums if val != num]) # Prints [3, 3]
use remove method to remove vlaues from list
nums = [3,2,2,3]
val = 2
l = list(nums)#creating new list
for v in l:
if v == val:
nums.remove(val)#removing values
print(nums)
output:
$ python3 file.py
[3, 3]

How to get position of an element from a nested list in python [duplicate]

This question already has answers here:
Find the index of an item in a list of lists
(6 answers)
Closed 2 years ago.
If I have a list that looks like this
list = [[1,2,3], [4,5,'X'], [7,8,'X']]
How can I get the position of X i.e like (i,j)?
list is a python keyword so it is probably better to use some other name. To access an element of list you can use this syntax: listname[indexNumber]. Note that index starts from 0. So, to access the X in the second list in the nested loop, you need to access the second list first; like this secondList = list[1]. Then you can get X which is in the second index position. x = secondList[2]. You can do this in the same line as well: print(list[1][2])
You can iterate over the "outer" list and use index on the inner list:
def find(matrix, item):
for i in range(len(matrix)):
try:
j = matrix[i].index(item)
return (i, j)
except ValueError:
pass
raise ValueError # If item isn't found
Try this
list1 = [[1,2,3], [4,5,'X'], [7,8,'X']]
print(list1[1][2])
print(list1[2][2])
If you don't know where 'X' will be every time:
test_list = [[1,2,3], [4,5,'X'], [7,8,'X']]
x = None
y = None
for separate_list in test_list:
for var in separate_list:
if var == 'X':
if x == None:
x = var
elif y == None:
y = var
pos = (x,y)
print(pos)
You can do this with list slicing.
l = [[1,2,3], [4,5,'X'], [7,8,'X']]
print(l[0][0], l[1][2], l[2][0])
print(l[1][2])
# [0][0] == first list in list and first item in the first list
# [1][2] == second list and third item in the second list
# [2][0] == third list and first item in that list
ouput
1 X 7
X
great python list slicing tuto here

Error : too many values to unpack (expected 2) - Python [duplicate]

This question already has answers here:
How do I iterate through two lists in parallel?
(8 answers)
Closed 6 years ago.
First of all below are the list not tuple also would like to append the data in both the list and above all that need to know the reason of error along with solution
Trying to compare two list basically, here "ref" is the reference list and "obt" is product list, while running code(below) an error is generated.
What is the solution for it?
Also would like to apply the same to the data frames in pandas, what should be the code for it?
ref =[1,2,3,4]
obt =[0.5,1,1.5,5]
i,j=0
for i,j in obt,ref:
global i,j
if (obt[i] <= ref[j]):
print ("all ok")
else:
print("error")
i=i+1
j=j+1
I think you would be good with zip:
for o, r in zip(obt, ref):
if o <= r:
print ("all ok")
else:
print("error")
Here is what zip(obt, ref) will produce:
[(0.5, 1), (1, 2), (1.5, 3), (5, 4)]
And, while looping over it you can compare the values from the tuple.
This assignment statement should not work:
i,j=0
Try this instead:
>>> i, j = 0, 0
>>> i
0
>>> j
0
But if you wanted to compare two different lists here's how you do it:
import itertools
for i, j in itertools.zip_longest(list1, list2):
# do stuff with i and j
# if either i or j is none then
# they are not the same lengths
You could also use a try, except statement if you are running into issues with lists of different length
Like:
try:
for i, j in obt, ref:
# Compare lists
except: # Enter error after except
# Do something else
You will need to use other variables then i and j. These will be altered by the for loop. It is better to use for x in range(len(list) for the indexing
Python for loops are actually foreach loops. You could do
ref =[1,2,3,4]
obt =[0.5,1,1.5,5]
for i in range(len(ref)):
if (obt[i] <= ref[i]):
print ("all ok")
else:
print("error")
The range function will iterate through the numbers 0 to the length of your array, range(len(ref)) = [0,1,2,3], you can then use for which in Python is actually a foreach to grab these numbers.
The enumerate function will give you both the index and the value, so you can also do
ref =[1,2,3,4]
obt =[0.5,1,1.5,5]
for i,r in enumerate(ref):
if (obt[i] <= r):
print ("all ok")
else:
print("error")
The enumerate function gives back the index and ref[i], which is being stored in i and r. This example better shows how Python is behaving like a foreach loop and not a for loop.
The reason for the error
On the line i,j=0, you have to give j a value as well, so you would do i,j=0,0. Now what happens here is that 0,0 is that same thing as (0,0). It's a tuple. The tuple then has to be unpacked. When a tuple is unpacked the first variable, i, gets the first value 0. The second variable, j, gets the second value. And if there where more values in the tuple this would continue until every value in the tuple is unpacked to some variable.
Once this is fixed we can proceed to the next line. for i,j in obt,ref. Once again, you will see the exact same error. This time python is expecting to iterate over something in the form of [(2 value tuple), (2 value tuple), (2 value tuple), (2 value tuple)].
The zip function can be used to create this structure, as has been suggested above, or if you prefer using the indexes in a for loop, you could use for i in range(len(ref)) to iterate over the list of indexes [0,1,2,3]. This
only work if ref and obt are the same length, otherwise you have to use zip.
Both ways work, using zip, or the method I mentioned, it's up to you how you want to solve the problem. If one list is longer than the other, zip will truncate the longer lists. The itertools.zip_longest solution that Games Braniac mentioned will extend the shortest length list so that they are the same size, and then zips them up.

How do I find the corresponding value when iterating two lists in Python? [duplicate]

This question already has answers here:
Accessing the index in 'for' loops
(26 answers)
Closed last month.
I would like to find the corresponding item in a list but the code below seems to find the corresponding item and then moves on item further as shown:
a = [1,2,3,4]
b = [5,6,7,8]
for i in a:
if i == 1:
print b[i]
Which gives me:
6
When I thought it should print:
5
In which case I'm now having to write:
print b[i-1]
python list index starts from 0 .
when you try to iterate a list you will be getting each and every element in the list
for example:
a = [1,2,3,4]
for element in a:
print element
will be printing [1,2,3,4]
incase if you want to get the index along with the element you should use
enumerate function
for example:
a = [1,2,3,4]
for index, element in enumerate(a):
print index, element
will be printing
0,1 where 0 is the index of 1 in list
1,2
2,3
3,4
in you program you can use enumerate to achieve what you want
a = [1,2,3,4]
b = [5,6,7,8]
for index, i in enumerate(a):
if i == 1:
print b[index]
will yield you the result you want.
Your condition is i==1, so when this is satisfied it naturally always looks up the second element (counting from 0) of b. (If the value 1 appeared at some other location in a, the workaround b[i-1] you are using would fail.)
I suspect what you want is
a = [1,2,3,4]
b = [5,6,7,8]
print b[a.index(1)]
(note that this avoids the unnecessary for loop). But your question isn't clear.
In your code, i==1 corresponds to the 0th element of a.
a.index(i) gives us the index with which we can print the corresponding element of b.
a = [1,2,3,4]
b = [5,6,7,8]
for i in a:
if i == 1:
print b[a.index(i)]
This would print the first element of b i.e 5
The reason, as everyone has mentioned, is because Python lists are 0-based.
When i == 1, you then print b[i] == b[1] == 2
To get the index, you need to use enumerate, which returns the index then the element at that index.
Here's how you should use it.
for idx, elem in enumerate(a):
if elem == 1:
print b[idx]

modifying one element modifies the whole column in python [duplicate]

This question already has answers here:
python lists, appending something to the list changes the entire thing?
(3 answers)
Closed 8 years ago.
x = raw_input("")
y = raw_input("")
a = []
b = []
count = 1
for i in range(0, int(y)):
b.append(count)
count+=1
for i in range(0, int(x)):
a.append(b)
for i in a:
print ""
for j in i:
print j,
a[1][1] = 0
for i in a:
print ""
for j in i:
print j,
a has been created by appending list "b" n time to it
Now when i modify a[1][1] the whole column that is a[0][1] - a[n][1] gets modified to that value
Can anyone explain why this is happening
Every time you append b, you are appending the same list -- not copies of the list, but multiple references to the same object. If you want each row to be a different list, you need to append a new list each time, by doing a.append(b[:]).
That is because by appending b, you are creating pointers to the same objects. Instead, make a copy as follows:
for i in range(0, int(x)):
a.append(b[:])
You can see it working as expected, here

Categories

Resources