This question already has answers here:
Slicing out a specific from a list
(2 answers)
Index all *except* one item in python
(11 answers)
Closed 2 years ago.
Is it possible to use slice but on a specific element on a list? For example a = [1,2,3,4,5,6,7,8,9] I want to make a for loop that prints out the whole list except the second element.
I want to make something like this:
for i in a[something_slice]:
print(i)
Is this possible?
For excluding just one element, the 2 slice lst[:i] + lst[i + 1:] approach proposed by #Applet123 is probably the fastest (Or perhaps a excluded = lst.pop(1) to extract the excluded element and for x in lst: print(x) for printing all the others; then lst.insert(1,excluded) to put the excluded element back on the list. See data structures docs for details).
If you just want to filter out certain indexes, instead of a for loop I recommend you use a more pythonic (and intuitive) approach based on list comprehensions and enumerate:
myList = [1,2,3,4,5,6,7,8,9]
excludedIndices = [1]
myFilteredList = [x for i, x in enumerate(myList) if i not in excludedIndices]
print (myFilteredList)
# output:
# [1,3,4,5,6,7,8,9]
# or, to actually print each element individually:
for x in myFilteredList:
print (x)
# which can also work as a 2-liner with inline filtering:
for i, x in enumerate(myList):
if i not in excludedIndices: print(x)
Also check out python usage of filter and map builtin functions, which may be overkill for this purpose but still offer a general and more powerful solution for this kind of processing:
# filters an enumerated element
def myFilter(element):
return element[0] not in excludedIndices
# maps an enumerated element to a function
def myMap(element):
print(element[1])
# runs myMap function for each enumerated element on the list filtered by myFilter
for x in map(myMap,filter(myFilter,enumerate(myList))): pass
Which you can also turn into a one-liner using lambda expressions:
for x in map(lambda x: print(x[1]),filter(lambda x: x[0] not in excludedIndices,enumerate(myList))): pass
you can do it without slicing, using enumerate()
index_to_skip=1
for idx,item in enumerate(a):
if idx!=index_to_skip:
print(item)
If you actually want to slice the list, you can use 2 slices to slice around it:
def exclude(lst, i):
return lst[:i] + lst[i + 1:]
exclude([1, 2, 3, 4, 5], 1) # [1, 3, 4, 5]
If you just want to loop through it, you could alternatively just skip when the index reaches the value you want to skip:
for i, v in enumerate(a):
if i == 1:
continue
print(v)
Related
This question already has answers here:
Remove all occurrences of a value from a list?
(26 answers)
Closed 1 year ago.
I want to remove the select element in sequence.
For example, I want to remove all 2 in sequence [1,2,3,2,3]
my code is
def remove_all(a_list, element):
for i in range(len(a_list)):
if element == a_list[i]:
a_list.remove(element)
return a_list
The output should be [1,3,3]
but the output of my code is [1,3,2,3]
I remove the first 2 but somehow the loop didn't go further to remove second 2. I wonder where is the problem of my code
Removing items in-place will almost certainly results in index errors.
[x for x in l if x != elem]
2 things.
You are modifying a list during iteration, I linked to a good read in my comment. also here
You return in the loop thus it stops at the return. Unindent the return, python is all about indentation unlike many other popular languages in this matter.
Try instead
Building another list for return:
def remove_all(a_list, element):
result = []
for ele in a_list:
if element != ele:
result.append(ele)
return result
Using a comprehension:
def remove_all(a_list, element):
return [ele for ele in a_list if ele != element]
a possible work-around is:
while element in a_list:
a_list.remove(element)
return element
But list comprehension works too, possibly even faster.
You should place the return after the loop finishes, something like:
def remove_all(a_list, element):
for i in a_list:
if element == i:
a_list.remove(element)
return a_list
a_list = [1, 2, 3, 2, 3]
result = remove_all(a_list, 2)
print(result)
Edit:
The code above does not work with the [2,2] case as pointed out in the comments.
Another solution would be:
myList = [2,2]
myList = list(filter((2).__ne__, myList))
print(myList)
Like that you don't copy the list anywhere, just is the list you are working on avoiding a list copy that can be expensive.
The __ne__ function checks that the element exists in the list returning True or False.
This question already has answers here:
Removing from a list while iterating over it [duplicate]
(5 answers)
Closed 6 years ago.
In a list, I have duplicate elements that I want to remove.
The following code doesn't work:
Note:
temp containts the list of indexes of elements that I want to remove.
x is my list.
temp = self.list_duplicates(x)
for index in tmp:
del x[index]
Build a new list with a comprehension:
x = [element for (i,element) in enumerate(x) if i not in temp]
If you want to remove only duplicates, i.e. leaving one copy of the original, there is a better way to do that:
from collections import OrderedDict
x = list(OrderedDict.fromkeys(x))
x.pop(index) will remove the item at index. However, x = [x[i] for i in range(len(x)) if x[i] not in x[:i]] will remove the duplicates more quickly.
No one addressed the first part of the question. So, for removing duplicate items its wise to use set(), it removes the duplicate items and returns a arbitrary list of unique items.
lst = [1,1,2,3,4,4]
new_lst = list(set(lst))
print(lst)
It will return unique list of elements in an arbitrary manner Eg : [1,4,2,3]
You can filter the list with the following:
Edit: Works now for list of indices
x = list(filter(lambda item: x.index(item) not in temp, x))
This question already has answers here:
elegant find sub-list in list
(7 answers)
Closed 6 years ago.
I have a Main List and a Sub List and I want to locate the indices of every occurrence of the Sub List that are found in the Main List, in this example, I want the following list of indices returned.
>>> main_list = [1,2,3,4,4,4,1,2,3,4,4,4]
>>> sub_list = [4,4,4]
>>> function(main_list, sub_list)
>>> [3,9]
Ideally, the function should also ignore fragments of the sub_list, in this case [4,4] would be ignored. Also, I expect the elements to all be single digit integers. Here is a second example, for clarity:
>>> main_list = [9,8,7,5,5,5,5,5,4,3,2,5,5,5,5,5,1,1,1,5,5,5,5,5]
>>> sub_list = [5,5,5,5,5]
>>> function(main_list, sub_list)
>>> [3,11,19]
Maybe using strings is the way to go?
import re
original = ''.join([str(x) for x in main_list])
matching = ''.join([str(x) for x in sub_list])
starts = [match.start() for match in re.finditer(re.escape(matching), original)]
The only problem with this one is that it doesn't count for overlapping values
You should be able to use a for loop, but then split it up into the length of you sub_list list, iterate through, and look for the sub lists in your main list. Try this:
main_list = [9,8,7,5,5,5,5,5,4,3,2,5,5,5,5,5,1,1,1,5,5,5,5,5]
sub_list = [5,5,5,5,5]
indices = []
for i in range(0, len(main_list)-len(sub_list)+1):
temp_array = main_list[i:i+len(sub_list)]
if temp_array == sub_list:
indices.append(i)
print indices
Here's a recursive way to do this:
list = [9,8,7,5,5,5,5,5,4,3,2,5,5,5,5,5,1,1,1,5,5,5,5,5]
def seq(array): # get generator on the list
for i in range(0,len(array)):
yield i
sq = seq(list) # get the index generator
def find_consecutive_runs(array): # Let's use generator - we are not passing index
i=next(sq) # get the index from generator
if len(array) > 5: # or 3, or 4, or whatever - get slice and proceed
arr = array[:5] # slice 5 elements
if all(x==arr[0] for x in arr): # all list elements are identical
print i # we found the index - let's print it
find_consecutive_runs(array[1:len(array)]) # proceed with recursion
find_consecutive_runs(list) # the actual call
I have a list of lists of tuples of integers.
ls = [[(a_1, a_2), (b_1, b_2)], [(c_1, c_2), (d_1, d_2), (e_1, e_2)], ...]
And I need to delete every item of ls that contains a tuple whose second entry is equal to a predetermined integer.
I tried this:
for item in ls:
for tpl in item:
if tpl[1] == m:
ls.remove(item)
But for some reason, this only removes a few of the list items but not all containing a tuple with second entry = m.
Use a list comprehension:
ls = [item for item in ls if all(tuple[1] != m for tuple in item)]
Or use a filter:
ls = filter(lambda item: all(tuple[1] != m for tuple in item),ls)
Code sucks and we need less of it - here's as sparse as it gets.
[l for l in ls if m not in [i[1] for i in l]]
The best way to filter a list in python is to use a list comprehension:
filtered = [item for item in ls if not(contains_m(item))]
And then all you need is a function that can tell if an item contains m, for example:
def contains_m(item):
return any([tpl[1] == m for tpl in item])
Removing an itme from list is not a good idea while iterating though it.
Try that (if where are talking Python here)
ls = [[('a_1', 'a_2'), ('b_1', 'b_2')], [('c_1', 'c_2'), ('d_1', 'd_2'), ('e_1', 'e_2')]]
m='c_2'
print [ x for x in ls if not [ y for y in x if y[1]==m ]]
Python's list iterator is lazy. This means that when you remove an item from the list, it will skip the next item. For example, say you want to remove all ones from the following list:
[1, 1, 2]
Your for loop starts at index 0:
[1, 1, 2]
^
It removes the element and moves on:
[1, 2]
^
This example is just to help illustrate the issue. One simple workaround is to loop backwards using the index:
for ind in range(len(ls)-1, -1, -1):
item = ls[ind]
for tpl in item:
if tpl[1] == m:
del ls[ind]
break # You can end the inner loop immediately in this case
Another way is to make a copy of the list to iterate over, but remove from the original:
for item in ls[:]:
for tpl in item:
if tpl[1] == m:
ls.remove(item)
break
The last approach can be simplified into creating an output list that contains only the elements that you want. This is easiest to do with a list comprehension. See #AlexeySmirnov 's answer for the best way to do that.
This question already has answers here:
Strange result when removing item from a list while iterating over it
(8 answers)
Closed 7 years ago.
For quite a bit of time now I have been trying to figure out a way to loop through a list and remove the current item that I'm at. I can't seem to get this working as I would like it to. It loops just 1 time through, but I wanted it to loop 2 times. When I remove the removal line - it loops 2 times.
a = [0, 1]
for i in a:
z = a
print z.remove(i)
The output:
[1]
The output that I was expecting:
[1]
[0]
You're changing the list while iterating over it -- z = a doesn't make a copy, it just points z at the same place a points.
Try
for i in a[:]: # slicing a list makes a copy
print i # remove doesn't return the item so print it here
a.remove(i) # remove the item from the original list
or
while a: # while the list is not empty
print a.pop(0) # remove the first item from the list
If you don't need an explicit loop, you can remove items that match a condition with a list comprehension:
a = [i for i in a if i] # remove all items that evaluate to false
a = [i for i in a if condition(i)] # remove items where the condition is False
It is bad practice modify a list while you're looping through it†. Create a copy of the list:
oldlist = ['a', 'b', 'spam', 'c']
newlist = [x for x in oldlist if x != 'spam']
To modify the original list, write the copy back in-place with a slice assignment:
oldlist[:] = [x for x in oldlist if x != 'spam']
† For a gist of why this might be bad practice, consider the implementation details of what goes on with the iterator over the sequence when the sequence changes during iteration. If you've removed the current item, should the iterator point to the next item in the original list or to the next item in the modified list? What if your decision procedure instead removes the previous (or next) item to the current?
The problem is that you're modifying a with remove so the loop exits because the index is now past the end of it.
Don't try to remove multiple items of a list while looping the list. I think it's a general rule you should follow not only in python but also in other programming languages as well.
You could add the item to be removed into a separate list. And then remove all objects in that new list from the original list.