I am trying to convert all elements of the small lists in the big list to integers, so it should look like this:
current list:
list = [['1','2','3'],['8','6','8'],['2','9','3'],['2','5','7'],['5','4','1'],['0','8','7']]
for e in list:
for i in e:
i = int(i)
new list:
list = [[1,2,3],[8,6,8],[2,9,3],[2,5,7],[5,4,1],[0,8,7]]
Could anyone tell me why doesn't this work and show me a method that does work? Thanks!
You can use a nested list comprehension:
converted = [[int(num) for num in sub] for sub in lst]
I also renamed list to lst, because list is the name of the list type and not recommended to use for variable names.
for e in range(len(List)):
for p in range(len(List[e])):
List[e][p] = int(List[e][p])
Or, you could create a new list:
New = [list(map(int, sublist)) for sublist in List]
Nested list comprehension is the best solution, but you can also consider map with lambda function:
lista = [['1','2','3'],['8','6','8'],['2','9','3'],['2','5','7'],['5','4','1'],['0','8','7']]
new_list = map(lambda line: [int(x) for x in line],lista)
# Line is your small list.
# With int(x) you are casting every element of your small list to an integer
# [[1, 2, 3], [8, 6, 8], [2, 9, 3], [2, 5, 7], [5, 4, 1], [0, 8, 7]]
In short, you are not mutating lst:
for e in lst:
for i in e:
# do stuff with i
is the equivalent of
for e in lst:
for n in range(len(e)):
i = e[n] # i and e[n] are assigned to the identical object
# do stuff with i
Now, whether the "stuff" you are doing to i is reflected in the original data, depends on whether it is a mutation of the object, e.g.
i.attr = 'value' # mutation of the object is reflected both in i and e[n]
However, string types (str, bytes, unicode) and int are immutable in Python and variable assignment is not a mutation, but a rebinding operation.
i = int(i)
# i is now assigned to a new different object
# e[n] is still assigned to the original string
So, you can make your code work:
for e in lst:
for n in range(len(e)):
e[n] = int(e[n])
or use a shorter comprehension notation:
new_lst = [[int(x) for x in sub] for sub in lst]
Note, however, that the former mutates the existing list object lst, while the latter creates a new object new_lst leaving the original unchanged. Which one you choose will depend on the needs of your program.
Related
I have a list of values and I want to move certain (or all) values to another list if they exist in a reference list.
x = [2,3,4,5,6,7,8] # list of values
ref = [2,3,4,5,6,7,8] # reference list
result = [x.pop(i) for i, v in enumerate(x) if v in ref]
But because of popping the current index, it ends up giving every other value instead. Is there a nice straightforward way to do this?
What I want at the end of this example is x=[] and result=[2,3,4,5,6,7,8], but ref doesn't need to contain all elements of x, this was just for an example. In another case it might be:
x = [2,3,4,5,6,7,8] # list of values
ref = [2,6,7] # reference list
So then I want x = [3,4,5,8] and result = [2,6,7]
In general, we should avoid modifying objects while iterating over them.
For this problem, we could generate result and filter x in two steps using comprehensions (avoiding appending to lists) as in the following example.
result, x = [v for v in x if v in ref], [v for v in x if v not in ref]
You could do it the old-fashioned way, with a while loop and a pointer into x:
x = [2, 3, 4, 5, 6, 7, 8]
ref = [2, 6, 7]
result = []
i = 0
while i < len(x):
if x[i] in ref:
result.append(x.pop(i))
else:
i += 1
print(x)
print(result)
Output:
[]
[2, 3, 4, 5, 6, 7, 8]
You can simply iterate from the end to the start to avoid pop() changing the list size while iterating. Just call reverse() on your new list after running your loop if the order of the list matters.
I am curious. How can I correctly iterate through a list, compare two values and delete the duplicate if it exists.
Here I created a nested for loop:
my_list = [ 1, 2, 3, 4, 5 ]
temp = [1, 5, 6]
def remove_items_from_list(ordered_list, temp):
# Removes all values, found in items_to_remove list, from my_list
for j in range(0, len(temp)):
for i in range(0, len(ordered_list)):
if ordered_list[i] == temp[j]:
ordered_list.remove(ordered_list[i])
But when I execute my my code I get an error:
File "./lab3f.py", line 15, in remove_items_from_list
if ordered_list[i] == items_to_remove[j]:
can anyone explain why?
This question, wanted to me compare two lists with one another, and these lists have two different lengths. If an item in list a matched a value in list b, we wanted then to delete it from list a.
You actually can remove items from a list while iterating over it but do read links by #ReblochonMasque.
Here is one way of removing duplicates:
def remove_items_from_list(ordered_list, temp):
n = len(ordered_list)
for i in range(n - 1, -1, -1):
if ordered_list[i] in temp:
del ordered_list[i]
Then
>>> remove_items_from_list(my_list, temp)
>>> print(my_list)
[2, 3, 4]
However, one of the easiest ways of solving your problem is to use sets:
list(set(my_list) - set(temp))
When using this approach, order of items in the resulting list may be arbitrary. Also, this will create a new list instead of modifying an existing list object. If order is important - use list comprehension:
[v for v in my_list if v not in temp]
While you iterating your loop, you remove item from orderer_list which cause index error
Try this:
def remove_items_from_list(ordered_list, temp):
list_ = [x for x in orderer_list if x not in temp]
return list_
first find the duplicated elements and then remove them from the original list.
dup_list = [item for item in temp if item in my_list]
for ele in dup_list:
my_list.remove(ele)
remove() source
You can't remove an items from the list you are iterating over. You can create a copy of the array and remove items from it.
I am testing a reverse function. My code is as follow:
def deep_reverse(L):
new_list = []
for element in L:
new_list += [element[::-1]]
L = new_list[::-1]
L = [[1, 2], [3, 4], [5, 6, 7]]
deep_reverse(L)
print(L)
I expect my output L can be like [[7, 6, 5], [4, 3], [2, 1]], but it only works inside my function.
I wasn't able to change it in the global variable. How can I make it happen? Thank you
L is just a local variable, and assigning a new object to it won't change the original list; all it does is point the name L in the function to another object. See Ned Batchelder's excellent explanation about Python names.
You could replace all elements in the list L references by assigning to the [:] identity slice instead:
L[:] = new_list[::-1]
However, mutable sequences like lists have a list.reverse() method, so you can just reverse the list in-place with that:
L.reverse()
Do the same for each sublist:
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 element in L:
element.reverse()
L.reverse()
I'm reading in a .csv file to a list and it appends an empty lists, I'm using the code below to do this.
with open('Scores.csv', 'r') as scores:
reader = csv.reader(scores)
tscores = [[str(e) for e in r] for r in reader]
It creates a list of nested lists correctly but appends an empty list after every row read in like so:
[[score1, name1], [], [score2, name2], []]
I believe it's reading \n as an empty string which is why I'm getting that, so I tried to remove empty lists using:
tscores = [tscores.remove(x) for x in tscores if x]
which does delete empty nested lists, but it sets all other nested lists that contained data to None i.e. [None, None]. I modified to:
tscores = [tscores.remove(x) for x in tscores if []]
which wipes out all nested lists completely.
How can I read the file with the same output (a list of nested lists) without appending empty lists or how can I remove all empty lists after being read in?
I think what you want to do is
tscores = [x for x in tscores if x != []]
which make a list of only the none empty lists in tscores
Alternative to user2990008's answer, you can not create the empty lists in the first place:
tscores = [[str(e) for e in r] for r in reader if len(r) > 0]
Just for completeness: In such cases I think that list comprehensions are not the most simple solution. Here functional programming would make sense, imho.
To "automatically" iterate over a list and filter specific elements, you could use the built-in function filter:
In [89]: a = [ [1, 2], [], [3, 4], [], [5, 6], [], [], [9, 5, 2, 5]]
In [91]: filter(lambda x: len(x) > 0, a)
Out[91]: [[1, 2], [3, 4], [5, 6], [9, 5, 2, 5]]
Every element x of the list a is passed to the lambda function and the returned list only contains an element of a if and only if the condition len(x) > 0 is met. Therefore a list without the nested empty lists is returned.
I'm not sure I'm understanding your question correctly, but you can remove the empty entries from a list of lists (or a list of tuples or a list of other sequences) using something like this:
#/bin/python
# ...
with open('Scores.csv', 'r') as scores:
reader = csv.reader(scores)
tscores = [[str(e) for e in r] for r in reader if len(r)]
... remember that your list comprehension can handle optional conditional clauses for filtering. This will only work if you can ensure that every element of the list that you're traversing support the len() function (of course you can ensure this by using a more complex condition such as: hasattr(r, 'len') and len(r)
Note: this only tests one level of depth ... it is not recursive.
tscores = [x for x in tscores if x]
If the list is empty the conditional will return false, and therefore will not be included in tscores.
Why is not possible to use a not in a for statement?
Assuming that both object and list are iterable
If you can't do that is there another way around?
Here is an example, but "obviously" a syntax error:
tree = ["Wood", "Plank", "Apples", "Monkey"]
plant = ["Flower", "Plank", "Rose"]
for plant not in tree:
# Do something
pass
else:
# Do other stuff
pass
Here's one way, using sets and assuming that both objects and list are iterable:
for x in set(objects).difference(lst):
# do something
First of all, you should not call a variable list, that'll clash with a built-in name. Now the explanation: the expression set(objects).difference(lst) performs a set difference, for example:
lst = [1, 2, 3, 4]
objects = [1, 2, 5, 6]
set(objects).difference(lst)
=> set([5, 6])
As you can see, we found the elements in objects that are not in the list.
If objects and list are two lists, and you want to iterate over every element of objects that isn't in list, you want the following:
for object in objects:
if object not in list:
do_whatever_with(object)
This loops over everything in objects and only processes the ones that aren't in list. Note that this won't be very efficient; you could make a set out of list for efficient in checking:
s = set(list)
for object in objects:
if object not in s:
do_whatever_with(object)
It looks like you are confusing a couple of things. The for loop is used to iterate over sequences (lists, tuples, characters of a string, sets, etc). The not operator reverses boolean values. Some examples:
>>> items = ['s1', 's2', 's3']
>>> for item in items:
... print item
...
s1
s2
s3
>>> # Checking whether an item is in a list.
... print 's1' in items
True
>>> print 's4' in items
False
>>>
>>> # Negating
... print 's1' not in items
False
>>> print 's4' not in items
True
If you mean to iterate over a list except few:
original = ["a","b","c","d","e"]
to_exclude = ["b","e"]
for item [item for item in orginal if not item in to_exclude]: print item
Produces:
a
c
d
You may use list comprehension combined with inline if:
>>> lst = [1, 2, 3, 4]
>>> objects = [1, 2, 5, 6]
>>> [i for i in objects if i not in lst]
[5, 6]
And another way:
from itertools import ifilterfalse
for obj in ifilterfalse(set(to_exclude).__contains__, objects):
# do something
Here is a simple way to achieve what you want:
list_i_have = [1, 2, 4]
list_to_compare = [2, 4, 6, 7]
for l in list_i_have:
if l not in list_to_compare:
do_something()
else:
do_another_thing()
Foreach item in the list you have, you can have a exclude list to check it is inside of list_to_compare.
You can also achieve this with list comprehension:
["it is inside the list" if x in (3, 4, 5) else "it is not" for x in (1, 2, 3)]