Related
I have a list that looks like the following one:
my_list = [[[(2,3,4,5)]],[[8,2,4,2]],[[9,0,0,0]]]
Now, I want to find a way to make a new list zero_list whose elements will be the 0th entries of each element in my_list. That is
zero_list = [2, 8, 9]
How could I make a for loop for iterating the 0th element of a list whose elements are lists themselves? Of course in my real example I have a much bigger such list with thousands of entries who are lists themselves.
P.S. I understand this is probably an easy question but I could not figure it out.
For any depth list you can use this recursive function
def get_first(seq):
if isinstance(seq, (tuple, list)):
return get_first(seq[0])
return seq
def get_zero_list(seq):
return [get_first(i) for i in seq]
my_list = [[[[[[[[(2,3,4,5)]]]]]]],[[8,2,4,2]],[[9,0,0,0]]]
print(get_zero_list(my_list)) # [2, 8, 9]
my_list = [[[[[[[[(2,3,4,5)]]]]]]],[[[[[[[('first', 3)]]]], 2, 3],2,4,2]],[[([['a', 2]]),0,0,0]]]
print(get_zero_list(my_list)) # [2, 'first', 'a']
Zero_list = [ items[0] for sublist in my_list for items in sublist]
I'm trying to create a function that reverses the order of the elements in a list, and also reverses the elements in a sublist. for example:
For example, if L = [[1, 2], [3, 4], [5, 6, 7]] then deep_reverse(L) mutates L to be [[7, 6, 5], [4, 3], [2, 1]]
I figured out how to reverse the order of one list, but I am having troubles with reversing the order of elements in a sublist. This is what I have so far:
def deep_reverse(L)
"""
assumes L is a list of lists whose elements are ints
Mutates L such that it reverses its elements and also
reverses the order of the int elements in every element of L.
It does not return anything.
"""
for i in reversed(L):
print(i)
In the example above, my code would just print [5,6,7], [3,4], [1,2], which is not what i'm trying to accomplish. It's just reversing the order of the lists, the not actual elements in the lists.
What should I add to the code so that it also reverses the order of the elements in a sublist?
[EDIT: my code needs to mutate the list; I don't want it just to print it, it actually needs to change the list.]
[sublist[::-1] for sublist in to_reverse[::-1]]
List comprehension works here. [::-1] is basically the same as reversed, but does not modify the list.
EDIT:
As pointed out below, reversed doesn't modify the list. It returns a listreverseiterator object
More Edit:
If you want a solution for lists of arbitrary depth, try:
def deep_reverse(to_reverse):
if isinstance(to_reverse, list):
return list(map(deep_reverse, to_reverse[::-1]))
else:
return to_reverse
Even more Edit:
To mutate a list in a function:
L[:] = new_list
Will modify the list in place.
I'm trying to create a function that reverses the order of the elements in a list, and also reverses the elements in a sublist.
Then do exactly those two things:
L.reverse()
for sublist in L:
sublist.reverse()
Full demo because you seem to be confused about what your function is supposed to do and how to test it:
>>> def deep_reverse(L):
"""
assumes L is a list of lists whose elements are ints
Mutates L such that it reverses its elements and also
reverses the order of the int elements in every element of L.
It does not return anything.
"""
L.reverse()
for sublist in L:
sublist.reverse()
>>> L = [[1, 2], [3, 4], [5, 6, 7]]
>>> deep_reverse(L)
>>> print(L)
[[7, 6, 5], [4, 3], [2, 1]]
Alternatively you use map() to achieve this as:
>>> map(lambda x: x[::-1], L[::-1]) # In Python 2.x
[[7, 6, 5], [4, 3], [2, 1]]
>>> list(map(lambda x: x[::-1], L[::-1])) # In Python 3.x
[[7, 6, 5], [4, 3], [2, 1]]
Check Blog on Lambda, filter, reduce and map to know how lambda functions and map() works in Python.
This should do the trick.
L = [[1, 2], [3, 4], [5, 6, 7]]
def deep_reverse(L):
for i in range(len(L)):
L[i]=L[i][::-1]
L=L[::-1]
return L
This looks very familiar :). I'm not going to give the whole working solution but here are some tips:
As you know, there are two steps, reverse each sub-list and then reverse the outer list (in place, without making a new list, so it will mutate the global L).
So you can loop through the outer list, and mutate each sub-list:
for i in range(len(L)):
# if L[i] is a list:
# reverse with [::-1] and update L[i] to the reversed version
# reverse the outer list L, list.reverse() will operate in-place on L
Now remember, if you loop through the list like this:
for item in list:
item = 'xxx'
You can't change item with the above code. item is a placeholder value, so changing it doesn't actually modify the list.
You instead need to index the item in L, and enumerate can help with this, or you can use the less-preffered range(len()) as above.
for i, item in enumerate(L):
# do something with L[i]
L[i] = 'something'
Edit: since there is so much confusion over this, I'll go ahead and post a working solution based on Stefan Pochmann's very elegant answer:
def deep_reverse(L):
L.reverse()
for sublist in L:
sublist.reverse()
Notice there is no return statement, and no print statement. This will correctly modify L in place. You cannot reassign L inside the function because then it will just create a new local version of L, and it will not modify the global L. You can use list.reverse() to modify L in place which is necessary based on the specifications.
with functional paradigm and defensive programming:
def deep_reverse(L):
""" assumes L is a list of lists whose elements are ints
Mutates L such that it reverses its elements and also
reverses the order of the int elements in every element of L.
It does not return anything.
"""
# Your code here
for i in L:
try:
deep_reverse(i)
except:
pass
L.reverse()
You could make this recursive, so it will work for arbitrarily deep nests.
something like (UNTESTED):
def deep_reverse(L)
"""
assumes L is a list of lists whose elements are ints
Mutates L such that it reverses its elements and also
reverses the order of the int elements in every element of L.
It does not return anything.
"""
for i in reversed(L):
if len(i) > 1:
deep_reverse(i)
else:
print(i)
Say for example:
list = { [1,2,3],[4,5,6],[3,4],[2,7,8,9] }
is there a way in python to remove a sublist and make sure that other sublists index's remain the same. So for example if i was to remove the sublist [3,4], could i make sure that the index of [2,7,8,9] remains as 3 in this case? if this is possible it would really be helpful! thanks!
Maybe. It depends on how you use the list and just how "listy" the resulting object needs to be.
l = [ [1,2,3],[4,5,6],[3,4],[2,7,8,9] ]
You could replace the sublist with something else like a None. Then your code would have to know to ignore None when it processes the list.
print(l[3])
l[2] = None
print(l[3])
or you could convert the list to a dict and delete the member. You can still index the object but since its now a dict, your code will have to treat it like a dict.
l = dict(enumerate(l))
print l[3]
del l[2]
print l[3]
These tricks will only work in some specialized environments.
You can just delete the elements in [3,4] and keep the empty sub-list.
>>> lst = [[1,2,3],[4,5,6],[3,4],[2,7,8,9]]
>>> del lst[2][:]
>>> lst
[[1, 2, 3], [4, 5, 6], [], [2, 7, 8, 9]]
Please note that you should not use list as a variable name as list is a built in function
But you can store the index with the value as a tuple. First make a modified list which has both index and value. Then you are free to remove any of the element.
lst = [[1,2,3],[4,5,6],[3,4],[2,7,8,9]]
modified = list(enumerate(lst))
To explain a bit:
modified=[]
for i,v in enumerate(lst):
modified.append((i,v))
print modified
Output:
[(0, [1, 2, 3]), (1, [4, 5, 6]), (2, [3, 4]), (3, [2, 7, 8, 9])]
As I am new to programming in Python. I am trying to remove particular elements from array using for loop which looks like
a=[2,3,1,4,1,1,1,5]
n=a.count(1)
for i in range (len(a)-n):
if (a[i]==1):
del a[i]
else:
a[i]=a[i]
print (a)
I want to remove 1 from array a. But, I am getting result as:
[2, 3, 4, 1, 1, 5].
That is 1 still exists in my new array. Can somebody please answer my problem?
try like this:
a = [2,3,1,4,1,1,1,5]
a = [x for x in a if x!=1] # this is called list comprehension
note Never modify list while iterating
Use a while loop and the remove method:
a = [2, 3, 1, 4, 1, 1, 1, 5]
while 1 in a:
a.remove(1)
print a
The real answer to your question (which none of the other answers addresses) is that every time you remove an item, the index i moves past it.
in your case:
a = [2,3,1,4,1,1,1,5]
after deleting the 5th item in the original list, the pointer moves to the 6th item, and the new 5th item (the second 1 in the sequence of three 1s) is skipped.
Regarding the comment never modify a list in a loop, try to implement an in-place algorithm like Fisher-Yates without modifying the list. Never say never. Know what you're doing.
The OP changes the list in-place, not creating a new list.
There are two methods, the second is safe, the first might be faster.
a = [2, 3, 1, 4, 1, 1, 1, 5]
toremove = 1
for i in range(len(a)-1, -1, -1):
if a[i] == toremove:
del a[i]
and
a = [2, 3, 1, 4, 1, 1, 1, 5]
toremove = 1
for i in range(a.count(toremove)):
a.remove(toremove)
The second removes the element however many times it exists (before the loop). Since we are not iterating on the list, it is safe to use the remove method.
Both fragments should be O(n) (but haven't done the calculations).
You can copy a and then remove but you cannot iterate over and delete elements from the same list, if your list starts with n elements python will have n pointers to each element so removing elements from the list as your are iterating over it will cause elements to be missed.python has no way of knowing you have removed elements from the list:
a = [2,3,1,4,1,1,1,5]
for ele in a[:]:
if ele == 1:
a.remove(1)
print(a)
[2, 3, 4, 5]
You can also use reversed which returns and iterator avoiding creating a whole copy of the list at once:
a = [2,3,1,4,1,1,1,5]
for ele in reversed(a):
if ele == 1:
a.remove(1)
print(a)
[2, 3, 4, 5]
Or using a list comprehension with the [:] syntax so we actually update the original object:
a[:] = (ele for ele in a if ele != 1)
All the above are linear operations using a single pass over a.
Actually as the del statement will remove elements from your list , and as the list that you bound in your loop doesn't been update after the first deleting you remove incorrect elements from your list , so if you want to use del you need to make the list name in your loop to reference to new list , that you can use a function for this aim , but as a more python way you can just use a list comprehension:
>>> a=[2,3,1,4,1,1,1,5]
>>> a=[i for i in a if i !=1]
>>> a
[2, 3, 4, 5]
Or you can use filter :
>>> a=[2,3,1,4,1,1,1,5]
>>> a=filter(lambda x: x !=1,a)
>>> a
[2, 3, 4, 5]
This question already has answers here:
Strange result when removing item from a list while iterating over it
(8 answers)
Closed 7 months ago.
In my Python 2.7.2 IDLE interpreter:
>>> mylist = [1, 2, 3, 4, 5]
>>> for item in mylist:
mylist.remove(item)
>>> mylist
[2, 4]
Why?
It's because when you iterate over a list, python keeps track of the index in the list. Consider the following code instead:
for i in range(len(mylist)):
if i >= len(mylist):
break
item = mylist[i]
mylist.remove(item)
If we track this (which is essentially what python is doing in your code), then we see that when we remove an item in the list, the number to the right shifts one position to the left to fill the void left when we removed the item. The right item is now at index i and so it will never actually get seen in the iteration because the next thing that happens is we increment i for the next iteration of the for loop.
Now for something a little clever. If instead we iterate over the list backward, we'll clear out the list:
for item in reversed(mylist):
mylist.remove(item)
The reason here is that we're taking an item off the end of the list at each iteration of the for loop. Since we're always taking items off the end, nothing needs to shift (assuming uniqueness in the list -- If the list isn't unique, the result is the same, but the argument gets a bit more complicated).
Of course, If you're looking to remove all the items from a list, you can do that really easily:
del mylist[:]
or even with slice assignment:
mylist[:] = []
(I mention the latter because it can be useful to replace segments of a list with other items which don't even need to be the same length).
That's because you're modifying the list while iterating over it, iterate over a shallow copy instead:
>>> mylist = [1, 2, 3, 4, 5]
>>> for item in mylist[:]: #use mylist[:] or list(mylist)
mylist.remove(item)
...
>>> mylist
[]
You are modifying your list while you are looping through it, which is very bad practice.
Problem is that you are altering the list while iterating on it. Use a list comprehension instead:
mylist = [1, 2, 3, 4, 5]
mylist = [x for x in mylist if condition(x)]
>>> mylist = [1, 2, 3, 4, 5]
>>> for item in mylist:
mylist.remove(item)
in this loop :
1st time it will take 0th element (1) as an item and remove it from mylist.so after that mylist will be [2,3,4,5] but the pointer will be in the 1th element of the new mylist ([2,3,4,5]) that is 3. and it will remove 3.so 2 will not be remove from the list.
thats why after the full operation [2,4] will be left.
using for loop:-
>>>for i in range(len(mylist)):
mylist.remove(mylist[0])
i-=1
>>>mylist
[]
you can do this using while loop:
>>>mylist = [1, 2, 3, 4, 5]
>>>while (len(mylist)>0):
mylist.remove(mylist[0])
print mylist
Use a deep copy of mylist
mylist = [1, 2, 3, 4, 5]
l = [k for k in mylist] # deep copy
for i in range(len(mylist)):
mylist.remove(l[i])
print
print mylist