Changing list while iterating [duplicate] - python

This question already has answers here:
Modifying a list while iterating over it - why not? [duplicate]
(4 answers)
Closed 6 years ago.
I've found a python puzzle and can't find out why it works.
x = ['a','b','c']
for m in x:
x.remove(m)
and after this loop x = ['b'].
But why?
As far as I understand for keyword implicitly creates iterator for this list. Does .remove() calls __next__() method so b is skipped? I can't find any mentions of it but this is my best guess.

Here you are iterating over the original list. On the first iteration, you removed the 0th index element i.e. a. Now, your list is as: ['b','c']. On the second iteration your for loop will access the value at index 1 but your index 1 has value c. So the c is removed. Hence resultant list will be ['b'].
In order to make it behave expectedly, iterate over the copy of the list, and remove the item from original list. For example:
x = ['a','b','c']
for m in list(x): # <-- Here 'list(x)' will create the copy of list 'x'
# for will iterate over the copy
x.remove(m)
# updated value of 'x' will be: []
Note: If it is not for demo purpose and you are using this code for emptying the list, efficient way of emptying the list will be:
del x[:]

Related

Iterating and changing elements in a list in Python [duplicate]

This question already has answers here:
Can't modify list elements in a loop [duplicate]
(5 answers)
Closed 4 years ago.
I'm supposed to find the largest number in a list, and then change all the elements of the list to that number. But when I print the output after the iteration, it still hasn't changed. What am I doing wrong please ?
Ar =[5,4,11]
ArMax = max(Ar)
for i in Ar:
i = ArMax
print(Ar)
The list doesn't change because you've done nothing to change the list. Your list is Ar -- where have you assigned a new value to anything in that list? Nowhere. All you did was to create a local variable to take on the values in Ar, and then change the value of that variable. You never touched the original list. Instead, you have to change the list elements themselves, not their copies. Keeping close to your present code:
for i in range(len(Ar)):
Ar[i] = ArMax
Another way would be to create a new list with those items in it, and simply replace the original list all at once:
Ar = [ArMax] * len(Ar)
This looks to see how long the current list is with len(Ar). Then it takes a one-element list with the max value and replicates it that many times. That new list becomes the new value of Ar.
i = ArMax does not actually assign values to the list because the values of i are copies of the elements in the list. If you want to fix this, try:
for i in xrange(len(Ar)):
Ar[i] = ArMax

How can I check if an object from one list is in another nested list? [duplicate]

This question already has answers here:
Python -Intersection of multiple lists?
(6 answers)
Closed 5 years ago.
say that I have a nested list like this for example:
List = [['a','d','b'],['a','x','w','t','d'],['g','c','d','z']]
and what I want to do is find the object in the List that all the smaller lists share, so for the example List I gave 'd' would be the object they all share.
here is what I have done so far:
def related(List):
for item in List[0]:
for i in range(1, len(List)):
if item in List[i]:
return item
the problem I am having is that when I do:
related([['a','d','b'],['a','x','w','t','d'],['g','c','d','z']])
'a' is returned, but that isn't the correct answer since 'a' isn't in all the lists and only in the first 2 lists. The correct answer with that list should be 'd'.
My function basically just stops running once it finds the same object in just 1 of the lists.
Will someone be able to send me towards the right path on what I can do to get my code working correctly? Thank You!!!
What you're looking for here is the intersection of these lists. Python lists don't have an intersection functionality built-in, but sets do. We can do
def in_common(l):
if not l:
return set()
return set(l[0]).intersection(*l[1:])
This converts the first element to a set, and then finds the intersection of that set with the rest of the elements in the list.
in_common([['a','d','b'],['a','x','w','t','d'],['g','c','d','z']])
returns
{'d'}
the set containing 'd'

Remove redundant square brackets in a list python [duplicate]

This question already has answers here:
How to access List elements
(5 answers)
Closed 5 years ago.
I am working with a list of lists longitudes and latitudes. Each inner list has an extra pair or square brackets.
For instance:
[[-87.77621462941525,-87.77676645562643,-87.77906119123564]]
I would like to remove the extra brackets and be left with:
[-87.77621462941525,-87.77676645562643,-87.77906119123564]
Thanks
this is nested list object, you can access the inner list with index.
In [1]: l = [[-87.77621462941525,-87.77676645562643,-87.77906119123564,]]
In [2]: l[0]
Out[2]: [-87.77621462941525, -87.77676645562643, -87.77906119123564]
List Indexing
You can simply use list indexing.
my_lists = [[-87.77621462941525,-87.77676645562643,-87.77906119123564,]]
my_list = my_lists[0]
next
Another way of doing this is using next which takes an iterable as an argument. It will raise a StopIteration in the case of the iterable being empty. You can prevent this by adding a default value as a second argument.
my_list = next(iter(my_lists))
Or
my_list = next(iter(my_list), []) # Using [] here but the second argument can be anything, really
Obviously this second option might be a bit of overkill for your case but I find it a useful one-liner in many cases. For example:
next_element = next(iter(list_of_unknown_size), None)
Versus
next_element = list_of_unknown_size[0] if list_of_unknown_size else None

How to get a copy from a list? [duplicate]

This question already has answers here:
How do I clone a list so that it doesn't change unexpectedly after assignment?
(24 answers)
Closed 9 years ago.
I am trying to get an element from list and make some change on this element (which is also a list). Weirdly, the change applied on the previous list. Here is my code:
>>>sentences[0]
['<s>/<s>',
'I/PRP',
'need/VBP',
'to/TO',
'have/VB',
'dinner/NN',
'served/VBN',
'</s>/</s>']
>>>sentence = sentences[0]
>>>sentence.insert(0,startc); sentence.append(endc)
>>>sentences[0]
['<s>/<s>',
'<s>/<s>',
'I/PRP',
'need/VBP',
'to/TO',
'have/VB',
'dinner/NN',
'served/VBN',
'</s>/</s>'
'</s>/</s>']
It is like I just got a pointer to that element, not a copy
You do get a "pointer", in fact. Lists (and any mutable value type!) are passed around as reference in Python.
You can make a copy of a list by passing it to the list() object constructor, or by making a full slice using [:].
a = [1,2,3]
b = a
c = list(a)
d = a[:]
a[1] = 4 # changes the list referenced by both 'a' and 'b', but not 'c' or 'd'
You're exactly right! In Python, when you pass a list as an argument to a function, or you assign a list to another variable, you're actually passing a pointer to it.
This is for efficiency reasons; if you made a separate copy of a 1000-item list every time you did one of the aforementioned things, the program would consume way too much memory and time.
To overcome this in Python, you can duplicate a one-dimensional list using = originalList[:] or = list(originalList):
sentence = sentences[0][:] # or sentence = list(sentences[0])
sentence.insert(0,startc)
sentence.append(endc)
print(sentence) # modified
print(sentences[0]) # not modified
Consider using list comprehension if you need to duplicate a 2D list.

python a=[[],]*10 [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Python list confusion
When I write a simple python script, I define a new list as follows:
A=[[],]*10
What I wanna do is just initialize a list whose length is 10 and each element is a empty list.
And when I do something like:
A[0].append(["abc",])
I just wanna append this ["abc",] to A[0], and it turn out to be that every elements in A is appended with ["abc",]
I know this probably due to my initialization (A=[[],]*10) . I just want to know why this happened.
Your expression A=[[]]*10 is equivalent to:
a = []
A = [a]*10
This means that A consists of 10 references to one and the same list.
You are creating a list with 10 references to the same empty list.
You should use a list comprehension instead:
A = [[] for _ in range(10)]
In a list comprehension, you create a new list for every iteration through the loop. If you are using python 2, you should use xrange instead of range (although with only 10 elements that won't make much difference).
All the empty lists are references to the same object.

Categories