python for loop with "reducing" list - python

a = [1,2,3,4]
for loop in range(0,len(a)):
if a[loop]%2==0:
a.remove(a[loop])
loop = loop - 1
I want to reduce the list by filtering numbers which can be divided by 2. There are two questions here:
I know this is a stupid method, is there a better (or a more pythonic) way?
If I really want to use the for-loop to tackle this task, as the actual filtering rule for the list is more complicated than 'dividable by two', I found that the 'iterative variable' loop is not reduced by one as expected in R, how can I make it working?
update 01
Thanks for the prompt reply, first part of the question is solved, but what about the second part? What if I want to use for-loop to deal with it and make the loop to be reduced by ` if the condition of 'dividable by two' is fulfilled?

If you want to remove all the elements from the list, if it is not divisible by 2, then the best way is to create a new list without the numbers not divisible by 2, like this
[item for item in a if item % 2 != 0]
You can also use the filter function, like this
filter(lambda item: item % 2 != 0, a)
If you are using Python 3.x, then you need to generate the list of items from the filter object using list function, like this
list(filter(lambda item: item % 2 != 0, a))
Apart from these methods, if you want to do in-place replacement, then you might want to do it in reverse, like this
a = [1,2,3,4]
for loop in range(len(a) - 1, -1, -1):
if a[loop] % 2 == 0:
a.remove(a[loop])
Note: Whenever possible, prefer list comprehension method.

You can use filter:
filter(lambda x: x % 2 == 0, a)

A list comprehension can do the trick:
# Define data in variable a
a = [1,2,3,4]
# Apply the list comprehension to filter list a
a = [i for i in a if i%2==0]

Related

Remove sublist from multidimensional list based on a condition [PYTHON] [duplicate]

I have a list List:
List = [-2,9,4,-6,7,0,1,-4]
For numbers less than zero (0) in the list , I would like to skip those numbers and form another list.
Example:-
List = [9,4,7,0,1]
This is a kind of doubt I have, not sure If we can achieve. If it's possible to achieve, can anyone please post here.
You have many options to achieve that. With a list comprehension you can do:
my_list = [i for i in my_list if i >= 0]
With filter():
my_list = filter(lambda i: i >= 0, my_list)
Note:
In Python 3, filter() returns a filter object (not list), to convert it to a list, you can do:
my_list = list(filter(lambda i: i >= 0, my_list))
First use lower case for variable names, second don't use list because it reserved name.
Then just do an if inside the list comprehension
my_list = [i for i in init_list if i >= 0 ]
I have tried this code here my_list = [i for i in init_list if i >= 0 ] but i had modified it to fit to my use and i would like to say that it can be used like this:
for i in [x for x in range(10) if != 3]
I used it here to make the program skip a iteration.

There is no counter in inline python?

When I'm trying to put counter in inline loop of Python, it tells me the syntax error. Apparently here it expects me to assign a value to i not k.
Could anyone help with rewriting the inline loop?
aa = [2, 2, 1]
k = 0
b = [k += 1 if i != 2 for i in aa ]
print(b)
You seem to misunderstand what you're doing. This:
[x for y in z]
is not an "inline for loop". A for loop can do anything, iterating on any iterable object. One of the things a for loop can do is create a list of items:
my_list = []
for i in other_list:
if condition_is_met:
my_list.append(i)
A list comprehension covers only this use case of a for loop:
my_list = [i for i in other_list if condition_is_met]
That's why it's called a "list comprehension" and not an "inline for loop" - because it only creates lists. The other things you might use a for loop for, like iterating a number, you can't directly use a list comprehension to do.
For your particular problem, you're trying to use k += 1 in a list comprehension. This operation doesn't return anything - it just modifies the variable k - so when python tries to assign that to a list item, the operation fails. If you want to count up with k, you should either just use a regular for loop:
for i in aa:
if i != 2:
k += 1
or use the list comprehension to indirectly measure what you want:
k += len([i for i in aa if i != 2])
Here, we use a list comprehension to construct a list of every element i in aa such that i != 2, then we take the number of elements in that list and add it to k. Since this operation actually produces a list of its own, the code will not crash, and it will have the same overall effect. This solution isn't always doable if you have more complicated things you'd like to do in a for loop - and it's slightly less efficient as well, because this solution requires actually creating the new list which isn't necessary for what you're trying to achieve.
you can use len() like so
print(len([i for i in a if i != 2]))

Skip elements on a condition based in a list comprehension in python

I have a list List:
List = [-2,9,4,-6,7,0,1,-4]
For numbers less than zero (0) in the list , I would like to skip those numbers and form another list.
Example:-
List = [9,4,7,0,1]
This is a kind of doubt I have, not sure If we can achieve. If it's possible to achieve, can anyone please post here.
You have many options to achieve that. With a list comprehension you can do:
my_list = [i for i in my_list if i >= 0]
With filter():
my_list = filter(lambda i: i >= 0, my_list)
Note:
In Python 3, filter() returns a filter object (not list), to convert it to a list, you can do:
my_list = list(filter(lambda i: i >= 0, my_list))
First use lower case for variable names, second don't use list because it reserved name.
Then just do an if inside the list comprehension
my_list = [i for i in init_list if i >= 0 ]
I have tried this code here my_list = [i for i in init_list if i >= 0 ] but i had modified it to fit to my use and i would like to say that it can be used like this:
for i in [x for x in range(10) if != 3]
I used it here to make the program skip a iteration.

How to iterate a list while deleting items from list using range() function? [duplicate]

This question already has answers here:
Strange result when removing item from a list while iterating over it
(8 answers)
Closed 7 years ago.
This is the most common problem I face while trying to learn programming in python. The problem is, when I try to iterate a list using "range()" function to check if given item in list meets given condition and if yes then to delete it, it will always give "IndexError". So, is there a particular way to do this without using any other intermediate list or "while" statement? Below is an example:
l = range(20)
for i in range(0,len(l)):
if l[i] == something:
l.pop(i)
First of all, you never want to iterate over things like that in Python. Iterate over the actual objects, not the indices:
l = range(20)
for i in l:
...
The reason for your error was that you were removing an item, so the later indices cease to exist.
Now, you can't modify a list while you are looping over it, but that isn't a problem. The better solution is to use a list comprehension here, to filter out the extra items.
l = range(20)
new_l = [i for i in l if not i == something]
You can also use the filter() builtin, although that tends to be unclear in most situations (and slower where you need lambda).
Also note that in Python 3.x, range() produces a generator, not a list.
It would also be a good idea to use more descriptive variable names - I'll presume here it's for example, but names like i and l are hard to read and make it easier to introduce bugs.
Edit:
If you wish to update the existing list in place, as pointed out in the comments, you can use the slicing syntax to replace each item of the list in turn (l[:] = new_l). That said, I would argue that that case is pretty bad design. You don't want one segment of code to rely on data being updated from another bit of code in that way.
Edit 2:
If, for any reason, you need the indices as you loop over the items, that's what the enumerate() builtin is for.
You can always do this sort of thing with a list comprehension:
newlist=[i for i in oldlist if not condition ]
As others have said, iterate over the list and create a new list with just the items you want to keep.
Use a slice assignment to update the original list in-place.
l[:] = [item for item in l if item != something]
You should look the problem from the other side: add an element to a list when it is equal with "something". with list comprehension:
l = [i for i in xrange(20) if i != something]
you should not use for i in range(0,len(l)):, use for i, item in enumerate(l): instead if you need the index, for item in l: if not
you should not manipulate a structure you are iterating over. when faced to do so, iterate over a copy instead
don't name a variable l (may be mistaken as 1 or I)
if you want to filter a list, do so explicitly. use filter() or list comprehensions
BTW, in your case, you could also do:
while something in list_: list_.remove(something)
That's not very efficient, though. But depending on context, it might be more readable.
The reason you're getting an IndexError is because you're changing the length of the list as you iterate in the for-loop. Basically, here's the logic...
#-- Build the original list: [0, 1, 2, ..., 19]
l = range(20)
#-- Here, the range function builds ANOTHER list, in this case also [0, 1, 2, ..., 19]
#-- the variable "i" will be bound to each element of this list, so i = 0 (loop), then i = 1 (loop), i = 2, etc.
for i in range(0,len(l)):
if i == something:
#-- So, when i is equivalent to something, you "pop" the list, l.
#-- the length of l is now *19* elements, NOT 20 (you just removed one)
l.pop(i)
#-- So...when the list has been shortened to 19 elements...
#-- we're still iterating, i = 17 (loop), i = 18 (loop), i = 19 *CRASH*
#-- There is no 19th element of l, as l (after you popped out an element) only
#-- has indices 0, ..., 18, now.
NOTE also, that you're making the "pop" decision based on the index of the list, not what's in the indexed cell of the list. This is unusual -- was that your intention? Or did you
mean something more like...
if l[i] == something:
l.pop(i)
Now, in your specific example, (l[i] == i) but this is not a typical pattern.
Rather than iterating over the list, try the filter function. It's a built-in (like a lot of other list processing functions: e.g. map, sort, reverse, zip, etc.)
Try this...
#-- Create a function for testing the elements of the list.
def f(x):
if (x == SOMETHING):
return False
else:
return True
#-- Create the original list.
l = range(20)
#-- Apply the function f to each element of l.
#-- Where f(l[i]) is True, the element l[i] is kept and will be in the new list, m.
#-- Where f(l[i]) is False, the element l[i] is passed over and will NOT appear in m.
m = filter(f, l)
List processing functions go hand-in-hand with "lambda" functions - which, in Python, are brief, anonymous functions. so, we can re-write the above code as...
#-- Create the original list.
l = range(20)
#-- Apply the function f to each element of l.
#-- Where lambda is True, the element l[i] is kept and will be in the new list, m.
#-- Where lambda is False, the element l[i] is passed over and will NOT appear in m.
m = filter(lambda x: (x != SOMETHING), l)
Give it a go and see it how it works!

How do you create a list like PHP's in Python?

This is an incredibly simple question (I'm new to Python).
I basically want a data structure like a PHP array -- i.e., I want to initialise it and then just add values into it.
As far as I can tell, this is not possible with Python, so I've got the maximum value I might want to use as an index, but I can't figure out how to create an empty list of a specified length.
Also, is a list the right data structure to use to model what feels like it should just be an array? I tried to use an array, but it seemed unhappy with storing strings.
Edit: Sorry, I didn't explain very clearly what I was looking for. When I add items into the list, I do not want to put them in in sequence, but rather I want to insert them into specified slots in the list.
I.e., I want to be able to do this:
list = []
for row in rows:
c = list_of_categories.index(row["id"])
print c
list[c] = row["name"]
Depending on how you are going to use the list, it may be that you actually want a dictionary. This will work:
d = {}
for row in rows:
c = list_of_categories.index(row["id"])
print c
d[c] = row["name"]
... or more compactly:
d = dict((list_of_categories.index(row['id']), row['name']) for row in rows)
print d
PHP arrays are much more like Python dicts than they are like Python lists. For example, they can have strings for keys.
And confusingly, Python has an array module, which is described as "efficient arrays of numeric values", which is definitely not what you want.
If the number of items you want is known in advance, and you want to access them using integer, 0-based, consecutive indices, you might try this:
n = 3
array = n * [None]
print array
array[2] = 11
array[1] = 47
array[0] = 42
print array
This prints:
[None, None, None]
[42, 47, 11]
Use the list constructor, and append your items, like this:
l = list ()
l.append ("foo")
l.append (3)
print (l)
gives me ['foo', 3], which should be what you want. See the documentation on list and the sequence type documentation.
EDIT Updated
For inserting, use insert, like this:
l = list ()
l.append ("foo")
l.append (3)
l.insert (1, "new")
print (l)
which prints ['foo', 'new', 3]
http://diveintopython3.ep.io/native-datatypes.html#lists
You don't need to create empty lists with a specified length. You just add to them and query about their current length if needed.
What you can't do without preparing to catch an exception is to use a non existent index. Which is probably what you are used to in PHP.
You can use this syntax to create a list with n elements:
lst = [0] * n
But be careful! The list will contain n copies of this object. If this object is mutable and you change one element, then all copies will be changed! In this case you should use:
lst = [some_object() for i in xrange(n)]
Then you can access these elements:
for i in xrange(n):
lst[i] += 1
A Python list is comparable to a vector in other languages. It is a resizable array, not a linked list.
Sounds like what you need might be a dictionary rather than an array if you want to insert into specified indices.
dict = {'a': 1, 'b': 2, 'c': 3}
dict['a']
1
I agree with ned that you probably need a dictionary for what you're trying to do. But here's a way to get a list of those lists of categories you can do this:
lst = [list_of_categories.index(row["id"]) for row in rows]
use a dictionary, because what you're really asking for is a structure you can access by arbitrary keys
list = {}
for row in rows:
c = list_of_categories.index(row["id"])
print c
list[c] = row["name"]
Then you can iterate through the known contents with:
for x in list.values():
print x
Or check if something exists in the "list":
if 3 in list:
print "it's there"
I'm not sure if I understood what you mean or want to do, but it seems that you want a list which
is dictonary-like where the index is the key. Even if I think, the usage of a dictonary would be a better
choice, here's my answer: Got a problem - make an object:
class MyList(UserList.UserList):
NO_ITEM = 'noitem'
def insertAt(self, item, index):
length = len(self)
if index < length:
self[index] = item
elif index == length:
self.append(item)
else:
for i in range(0, index-length):
self.append(self.NO_ITEM)
self.append(item)
Maybe some errors in the python syntax (didn't check), but in principle it should work.
Of course the else case works also for the elif, but I thought, it might be a little harder
to read this way.

Categories

Resources