List erasing unexpected behavior [duplicate] - python

This question already has answers here:
Removing from a list while iterating over it [duplicate]
(5 answers)
How to remove items from a list while iterating?
(25 answers)
Closed 6 years ago.
I am trying to clear a python list by removing every element in loop by code
x=list(range(10000))
for i in x:
x.remove(i)
I thought that after this code x must be [], but instead only every second element of list is removed. len(x)=5000 instead of 0.
Why is it so? What am I doing wrong.
Thanks

The a.remove(i) messed up the indexing is my guess.
instead use
a.clear()
Its a good way to clear a list.

If you want to clear a python list like you're doing, the right way is just using x.clear, docs about that method here, now, if you want to remove elements using some fancy conditions, just use filter, example clearing the whole x list:
x = list(range(10000))
x = filter(lambda x: False, x)
print x

If you want to implement a list object that erases itself while iterating over it that would be fairly easy:
class ErasingList(list):
"a list implemented as an iterator, iterating over it will .pop() items off"
def __iter__(self):
return self
def __next__(self):
try:
return self.pop(0)
#or self.pop() to take from the end of the list which is less intuitive but more efficient
except IndexError:
raise StopIteration
next = __next__ #vs2 compatibility.
x = ErasingList(range(100))
for i in x:
print(i)
print(x)

original_list = list(range(1000))
remove_list_elements = []
for i in range(0, len(original_list), 2):
remove_list_elements.append(original_list[i])
[original_list.remove(i) for i in remove_list_elements]
print(len(original_list))

Related

Need help understanding a specific type of for loop [duplicate]

This question already has answers here:
What does "list comprehension" and similar mean? How does it work and how can I use it?
(5 answers)
Closed 6 months ago.
I am still relatively new to coding. I've been doing this for less than a year and most of the basics I completely understand now. However, every now and then I come across a type of for loop that I can't get my head around.
It usually goes like this:
x for x in list if x in otherList
I completley understand for loops and if statements. But that particular line of code always confuses me. Would anyone be able to provide a detailed explanation of what actually is happening there, please?
It's called a list comprehension if it's in brackets []:
This:
new_list = [x for x in my_list if x in other_list]
Is equivalent to this:
new_list = []
for x in my_list:
if x in other_list:
new_list.append(x)
If it's in parentheses () it's called a generator:
This:
new_list = (x for x in my_list if x in other_list)
Is sort of equivalent to this:
def foo():
for x in my_list:
if x in other_list:
yield x
new_list = foo()
You might want to read this question and answer to understand more about generators and yielding functions.
This is used within a list comprehension and the if statement acts as a filter.
You may begin with a list of all numbers from 0-9:
mynums = range(10)
But then you might want only the even numbers in a new list:
myevennums=[]
for i in mynums:
if mynums%2 ==0:
myevennums.append(i)
That works but so many keystrokes 😭
So python allows list comprehensions:
myevennums = [i for i in mynums if i%2==0]
The condition could be anything, including membership in another list:
evens_to_20 = list(range(0,21,2))
Then you could create a list with the elements of your list that are also in the other list:
myevennums = [i for i in mynums if i in evens_to_20]
In general, when you see a statement like that you can always expand it as:
Y_comprehension = [i for i in X if condition(i)]
# the same as
Y_loop=[]
for i in X:
if condition(i):
Y_loop.append(i)
assert Y_comprehension == Y_loop
If the condition really is very simple, the list-comprehension is usually the better choice. If it starts to get complicated, you probably want the loop or an intermediate function def condition(item): ...

what will be the efficient way of knowing that only integer data is present in a list in python 3 [duplicate]

This question already has answers here:
How to test if every item in a list of type 'int'?
(7 answers)
Closed 2 years ago.
I am trying to achieve a way of checking if the elements of a list are integers or not and after that, I want to throw an assertion error if they are not.
One way I found is to iterate over the list and check for each element data-type. But is there any efficient approach out there to test the same?
I am trying to achieve something like this,
def add_edge(self, edge):
assert len(edge) != 2, "edge list length not equal to 2, enter a list of length 2"
assert is_any_element_non_int, "expected data type to be int, but found another"
stay with generator is recommended in terms of efficiency:
a = [1,2,3]
b = ["1", 2]
print(all(isinstance(item, int) for item in a)) # True
print(all(isinstance(item, int) for item in b)) # False
Try Like this:
if all(isinstance(x,int) for x in myList) == True:
# YEAH TRUE
else:
# ALAS EXCEPTION throw error

How can I split a list every time the value changes? [duplicate]

This question already has answers here:
How do I use itertools.groupby()?
(15 answers)
Closed 3 years ago.
I have a list of values, 7,7,7,7,7,7,7,7,6,6,6,6,6,6,7,7,7,7,7,8,8,8,8,8,8,8,8,5,5,5,5,5,5,6,6,6,6,6 etc and I need to split the list into the list of list format every time there is a change in value, such that it becomes [[7,7,7,7,7,7,7,7],[6,6,6,6,6,6],[7,7,7,7,7],[8,8,8,8,8,8,8,8],[5,5,5,5,5,5],[6,6,6,6,6]].
I tried a code as follows, however, it told me that there was an unexpected token "for". Is there any other way that's cleaner (one liners)?
for i, n in enumerate(x):
inds = []
if x[i] != x[i-1]:
inds.append(i)
list(split_after(x, lambda i: i for i in inds))
Edit: I can't use groupby because it requires me to sort the list, and I'm concurrently using this list to sort another list of lines, and I can't reorder the other list because of how it's sorted to be lines running ordered around my entire surface.
You can try the following:
indexes = [index for index, _ in enumerate(x) if x[index] != x[index-1]]
indexes.append(len(x))
final = [x[indexes[i]:indexes[i+1]] for i, _ in enumerate(indexes) if i != len(indexes)-1]
print(final)

Iterating - Python [duplicate]

This question already has answers here:
How to remove items from a list while iterating?
(25 answers)
Closed 5 years ago.
Trying to remove negative numbers from a list. I kept running into an issue where two successive negative numbers did not get removed. My code is quite simple:
numbers = [-5, 1, -3, -1]
def remove_neg(num_list):
for item in num_list:
if item < 0:
num_list.remove(item)
print(remove_neg(numbers))
#[1, -1]
I found the answer online after trying 4 different versions of my code and pulling a few hairs out of my head. The answer I found assigned r = numbers[:] and then removed items from r instead of the initial list.
def remove_neg(num_list):
r = numbers [:]
for item in num_list:
if item < 0:
r.remove(item)
print(r)
I understand this concept to have two list variables point to separate data. What I don't understand, is why my initial code doesn't work. Shouldn't for i in numbers: iterate through every item in the list? Why would two successive numbers not be treated the same? I've scoured looking for why and can't seem to find an answer.
In the first example you're modifying the list while iterating over it, which, as you've seen, messes up the iteration. While the second example works, it's very inefficient, and it would be much easier to use a list comprehension to construct a new list without the negatives:
def remove_neg(num_list):
return [x for x in num_list if x > 0]

Why doesn't filter method return a list? [duplicate]

This question already has answers here:
How to use filter, map, and reduce in Python 3
(7 answers)
Closed 5 years ago.
I am learning the concept of filters in Python. I am running a simple code like this.
>>> def f(x): return x % 2 != 0 and x % 3 != 0
>>> filter(f, range(2, 25))
But instead of getting a list, I am getting some message like this.
<filter object at 0x00FDC550>
What does this mean? Does it means that my filtered object i.e list to come out is stored at that memory location? How do I get the list which I need?
It looks like you're using python 3.x. In python3, filter, map, zip, etc return an object which is iterable, but not a list. In other words,
filter(func,data) #python 2.x
is equivalent to:
list(filter(func,data)) #python 3.x
I think it was changed because you (often) want to do the filtering in a lazy sense -- You don't need to consume all of the memory to create a list up front, as long as the iterator returns the same thing a list would during iteration.
If you're familiar with list comprehensions and generator expressions, the above filter is now (almost) equivalent to the following in python3.x:
( x for x in data if func(x) )
As opposed to:
[ x for x in data if func(x) ]
in python 2.x
It's an iterator returned by the filter function.
If you want a list, just do
list(filter(f, range(2, 25)))
Nonetheless, you can just iterate over this object with a for loop.
for e in filter(f, range(2, 25)):
do_stuff(e)

Categories

Resources