Python List removal issue [duplicate] - python

This question already has answers here:
for loop ignores some elements of my list [duplicate]
(2 answers)
Closed 9 years ago.
I am removing elements from a list. But using for to iterate through the elements , I can see that alternate elements are being accessed, hence all elements are not getting deleted.
Code
l = ['A','B','C','D','E','F']
for x in l:
l.remove(x)
print "My List:"+str(l)
print "Final List:"+str(l)
Output
My List:['B', 'C', 'D', 'E', 'F']
My List:['B', 'D', 'E', 'F']
My List:['B', 'D', 'F']
Final List:['B', 'D', 'F']
Can you please suugest any modification in this logic which would sort the issue. Alternatively if there is a better approach to this.

You should not modify the list you are iterating upon, else you are bound to get wierd results.
Rather iterate over a copy of list:
for x in l[:]:
l.remove(x)

An alternative to copying the list (and would make more sense imo given the context):
In [1]: from collections import deque
In [2]: l = deque(['A','B','C','D','E','F'])
In [3]: while len(l) > 0:
...: l.popleft()
...: print l
...:
deque(['B', 'C', 'D', 'E', 'F'])
deque(['C', 'D', 'E', 'F'])
deque(['D', 'E', 'F'])
deque(['E', 'F'])
deque(['F'])
deque([])

How about this? This does not make up any new list.
l = ['A','B','C','D','E','F']
while l: del l[0]; print("My List:"+str(l))
print("Final List:"+str(l))

Instead of deleting elements from the list, you could just slice it:
l = ['A','B','C','D','E','F']
for i in range(len(l) + 1):
print "My List:"+str(l[i:])

It seems what you want is just removing all the elements from the list. I think you can just use:
l = []
Or if there is a condition, you can use list comprehension:
[x for x in l in if x ...]

Related

Splitting string values in list into individual values, Python

I have a list of values in which some values are words separated by commas, but are considered single strings as shown:
l = ["a",
"b,c",
"d,e,f"]
#end result should be
#new_list = ['a','b','c','d','e','f']
I want to split those strings and was wondering if there's a one liner or something short to do such a mutation. So far what, I was thinking of just iterating through l and .split(',')-ing all the elements then merging, but that seems like it would take a while to run.
import itertools
new_list = list(itertools.chain(*[x.split(',') for x in l]))
print(new_list)
>>> ['a', 'b', 'c', 'd', 'e', 'f']
Kind of unusual but you could join all your elements with , and then split them:
l = ["a",
"b,c",
"d,e,f"]
newList = ','.join(l).split(',')
print(newList)
Output:
['a', 'b', 'c', 'd', 'e', 'f']
Here's a one-liner using a (nested) list comprehension:
new_list = [item for csv in l for item in csv.split(',')]
See it run here.
Not exactly a one-liner, but 2 lines:
>>> l = ["a",
"b,c",
"d,e,f"]
>>> ll =[]
>>> [ll.extend(x.split(',')) for x in l]
[None, None, None]
>>> ll
['a', 'b', 'c', 'd', 'e', 'f']
The accumulator needs to be created separately since x.split(',') can not be unpacked inside a comprehension.

How to combine every element of a list to the other list? [duplicate]

This question already has answers here:
Element-wise addition of 2 lists?
(17 answers)
Closed 5 years ago.
Suppose there are two lists:
['a', 'b', 'c'], ['d', 'e', 'f']
what I want is:
'ad','ae','af','bd','be','bf','cd','ce','cf'
How can I get this without recursion or list comprehension? I mean only use loops, using python?
The itertools module implements a lot of loop-like things:
combined = []
for pair in itertools.product(['a', 'b', 'c'], ['d', 'e', 'f']):
combined.append(''.join(pair))
While iterating through the elements in the first array, you should iterate all of the elements in the second array and push the combined result into the new list.
first_list = ['a', 'b', 'c']
second_list = ['d', 'e', 'f']
combined_list = []
for i in first_list:
for j in second_list:
combined_list.append(i + j)
print(combined_list)
This concept is called a Cartesian product, and the stdlib itertools.product will build one for you - the only problem is it will give you tuples like ('a', 'd') instead of strings, but you can just pass them through join for the result you want:
from itertools import product
print(*map(''.join, product (['a','b,'c'],['d','e','f']))

Reverse a List by Swap Ends

I am trying to reverse a list's order by finding three bugs in this function. This function is supposed to reverse the first and last elements of a list, the second and second to last elements, and so on. I believe I found two, but am having trouble fixing the line of list[j] = y.
def reverse(list):
"""Reverses elements of a list."""
for i in range(len(list)):
j = len(list) - i
x = list[i]
y = list[j-1]
list[i] = x
list[j] = y
l = ['a', 'b', 'c', 'd', 'e']
reverse(l)
print(l)
Homework I suspect...
But - we all need a break from homework. By looping over the whole list you're reversing it twice.
def reverse(list):
"""Reverses elements of a list."""
for i in range(len(list)/2):
j = i + 1
x = list[i]
y = list[-j]
list[-j] = x
list[i] = y
l = ['a', 'b', 'c', 'd', 'e']
l=reverse(l)
print(l)
resulting in
['e', 'd', 'c', 'b', 'a']
You have a couple problems. Your first problem is that you use list[j] = y instead of list[j-1] = x. You defined y correctly with j-1, but you should be changing list[j-1] to the other one, x. Another problem is that you are going from the beginning of the list all the way to the end. Once you get to more than half way through the list, you are undoing your work. You also don't need to use len(list)-i because you can just use -i. Here is the updated code:
def reverse(seq):
"""Reverses elements of a list."""
for i in range(len(seq)//2):
x = seq[i]
y = seq[-i-1]
seq[i] = y
seq[-i-1] = x
l = ['a', 'b', 'c', 'd', 'e']
reverse(l)
print(l)
Output:
['e', 'd', 'c', 'b', 'a']
You don't even need to define x and y. Instead, do this:
def reverse(seq):
"""Reverses elements of a list."""
for i in range(len(list)//2):
seq[i], seq[-i-1] = seq[-i-1], seq[i]
I also changed your naming. There's probably a better name than seq, but list is unacceptable because it conflicts with the built-in type.
Use this code:
l = ['a', 'b', 'c', 'd', 'e']
l=l[::-1]
print(l)
Why you want to complicate this simple construction? Or if you don't wanna do this on that way, try to use:
l.reverse()
function. Python has a lot of functions ready to use.

Check list item against multiple lists and remove if present in any of them. Python [duplicate]

This question already has answers here:
remove elements in one list present in another list [duplicate]
(2 answers)
Closed 8 years ago.
I have a main list such as:
mainlst = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
and I want to search each item in this mainlst against multiple other search lists and if it's present in any of them to remove it from the main list, so for example:
searchlst1 = ['a', 'b', 'c']
searchlst2 = ['a', 'd', 'f']
searchlst3 = ['e', 'f', 'g']
The issue Im having is I cant work out how to make the loop go through each statement, so if I use and if elif statement it exits the loop as soon as it has found a match
for item in mainlst:
if item in searchlst1:
mainlst.remove(item)
elif item in searchlst2:
mainlst.remove(item)
elif item in searchlst3
mainlst.remove(item)
but obviously this exits the loop as soon as one condition is true, how do I make the loop go through all the conditions?
set objects are great for stuff like this -- the in operator takes O(1) time compared to O(N) time for a list -- And it's easy to create a set from a bunch of existing lists using set.union:
search_set = set().union(searchlst1, searchlst2, searchlst3)
mainlst = [x for x in mainlst if x not in search_set]
Example:
>>> search_set = set().union(searchlst1, searchlst2, searchlst3)
>>> search_set
set(['a', 'c', 'b', 'e', 'd', 'g', 'f'])
>>> mainlst = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
>>> mainlst = [x for x in mainlst if x not in search_set]
>>> mainlst
['h']
How about using a list comprehension and a set:
[i for i in mainlst if i not in set(searchlst1 + searchlst2 + searchlst3)]
returns ['h']
set() takes an iterable (in this case a group of lists) and returns a set containing the unique values. Tests for membership in a set always take the same amount of time, whereas testing for membership in a list scales linearly with the length of the list.
The list comprehension goes through each element of mainlst and constructs a new list whose members are not in the set:
>>> mainlst = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
>>> search = set(searchlst1 + searchlst2 + searchlst3)
>>> search
set(['a', 'c', 'b', 'e', 'd', 'g', 'f'])
>>> [i for i in mainlst if i not in search]
['h']
Replacing the elif statements with if statements will fix your problem.
for item in mainlst:
if item in searchlst1:
mainlst.remove(item)
if item in searchlst2:
mainlst.remove(item)
if item in searchlst3:
mainlst.remove(item)
The problem now is that your doing three searches through the list to remove items. This will become more time consuming as the list or searchlists grow. And in your example there are duplicates in your searchlists.
Combining the searchlists will reduce number of comparisons.

Removing element messes up the index [duplicate]

This question already has answers here:
Loop "Forgets" to Remove Some Items [duplicate]
(10 answers)
Closed 8 years ago.
I have a simple question about lists
Suppose that I want to delete all 'a's from a list:
list = ['a', 'a', 'b', 'b', 'c', 'c']
for element in list:
if element == 'a':
list.remove('a')
print list
==> result:
['a', 'b', 'b', 'c', 'c', 'd', 'd']
I know this is happening because, after I remove the first 'a', the list index gets
incremented while all the elements get pushed left by 1.
In other languages, I guess one way to solve this is to iterate backwards from the end of the list..
However, iterating through reversed(list) returns the same error.
Is there a pythonic way to solve this problem??
Thanks
One of the more Pythonic ways:
>>> filter(lambda x: x != 'a', ['a', 'a', 'b', 'b', 'c', 'c'])
['b', 'b', 'c', 'c']
You should never modify a list while iterating over it.
A better approach would be to use a list comprehension to exclude an item:
list1 = ['a', 'a', 'b', 'b', 'c', 'c']
list2 = [x for x in list1 if x != 'a']
Note: Don't use list as a variable name in Python - it masks the built-in list type.
You are correct, when you remove an item from a list while iterating over it, the list index gets out of sync. What both the other existing answers are hinting at is that you need to create a new list and copy over only the items you want.
For example:
existing_list = ['a', 'a', 'b', 'c', 'd', 'e']
new_list = []
for element in existing_list:
if element != 'a':
new_list.append(element)
existing_list = new_list
print existing_list
outputs: ['b', 'c', 'd', 'e']

Categories