Related
So heres my code:
item = [0,1,2,3,4,5,6,7,8,9]
z = [] # list of integers
for item in z:
if item not in z:
print item
z contains a list of integers. I want to compare item to z and print out the numbers that are not in z when compared to item.
I can print the elements that are in z when compared not item, but when I try and do the opposite using the code above nothing prints.
Any help?
Your code is not doing what I think you think it is doing. The line for item in z: will iterate through z, each time making item equal to one single element of z. The original item list is therefore overwritten before you've done anything with it.
I think you want something like this:
item = [0,1,2,3,4,5,6,7,8,9]
for element in item:
if element not in z:
print(element)
But you could easily do this like:
[x for x in item if x not in z]
or (if you don't mind losing duplicates of non-unique elements):
set(item) - set(z)
>> items = [1,2,3,4]
>> Z = [3,4,5,6]
>> print list(set(items)-set(Z))
[1, 2]
Using list comprehension:
print [x for x in item if x not in Z]
or using filter function :
filter(lambda x: x not in Z, item)
Using set in any form may create a bug if the list being checked contains non-unique elements, e.g.:
print item
Out[39]: [0, 1, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print Z
Out[40]: [3, 4, 5, 6]
set(item) - set(Z)
Out[41]: {0, 1, 2, 7, 8, 9}
vs list comprehension as above
print [x for x in item if x not in Z]
Out[38]: [0, 1, 1, 2, 7, 8, 9]
or filter function:
filter(lambda x: x not in Z, item)
Out[38]: [0, 1, 1, 2, 7, 8, 9]
list1 = [1,2,3,4]; list2 = [0,3,3,6]
print set(list2) - set(list1)
If you run a loop taking items from z, how do you expect them not to be in z? IMHO it would make more sense comparing items from a different list to z.
No, z is undefined. item contains a list of integers.
I think what you're trying to do is this:
#z defined elsewhere
item = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
for i in item:
if i not in z: print i
As has been stated in other answers, you may want to try using sets.
>>> item = set([0,1,2,3,4,5,6,7,8,9])
>>> z = set([2,3,4])
>>> print item - z
set([0, 1, 5, 6, 7, 8, 9])
Your code is a no-op. By the definition of the loop, "item" has to be in Z. A "For ... in" loop in Python means "Loop though the list called 'z', each time you loop, give me the next item in the list, and call it 'item'"
http://docs.python.org/tutorial/controlflow.html#for-statements
I think your confusion arises from the fact that you're using the variable name "item" twice, to mean two different things.
You are reassigning item to the values in z as you iterate through z. So the first time in your for loop, item = 0, next item = 1, etc... You are never checking one list against the other.
To do it very explicitly:
>>> item = [0,1,2,3,4,5,6,7,8,9]
>>> z = [0,1,2,3,4,5,6,7]
>>>
>>> for elem in item:
... if elem not in z:
... print elem
...
8
9
In the case where item and z are sorted iterators, we can reduce the complexity from O(n^2) to O(n+m) by doing this
def iexclude(sorted_iterator, exclude_sorted_iterator):
next_val = next(exclude_sorted_iterator)
for item in sorted_iterator:
try:
while next_val < item:
next_val = next(exclude_sorted_iterator)
continue
if item == next_val:
continue
except StopIteration:
pass
yield item
If the two are iterators, we also have the opportunity to reduce the memory footprint not storing z (exclude_sorted_iterator) as a list.
If the lists are sorted and you know the elements of the checking list are in the base list - you can do a more optimal O(n) solution by using two pointers (where n will be the length of the base_list:
base_list = [0, 1, 2, 3, 4, 5, 6, 7, 8]
checking_list = [1, 3, 5]
expected_return = [0, 2, 4, 6, 7, 8]
j = 0
i = 0
elements_not_in_checking_list = []
while i < len(base_list):
if j < len(checking_list) and base_list[i] == checking_list[j]:
i += 1
j += 1
else:
elements_not_in_checking_list.append(base_list[i])
i += 1
Many of the solutions already posted here will not preserve the original ordering of the elements (because sets are unordered) or are inefficient (because linear search in a list is slower than a lookup in a set).
You can make a set of elements to remove upfront, and then use a list comprehension to retain only the elements which aren't in the set:
items = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
z = [3, 4, 5, 6]
set_z = set(z)
result = [e for e in items if e not in set_z]
Then, result contains:
[0, 1, 2, 7, 8, 9]
I'm learning python and I'm a bit puzzled by some behavior of lists when I create one using the range function. Hopefully someone can help me wrap my head around this? Here is a block of code I wrote:
elements = []
elements.append(range(1, 6))
for number in elements:
print "Line %d" % number
When I run this, I get the error for line 4:
TypeError: %d format: a number is required, not list
If I re-write the code as such:
elements = []
for i in range(1, 6):
elements.append(i)
for number in elements:
print "Line %d" % number
it runs how I expected the first block would.
If I replace the %d with a %r, it prints the list as
Line [1, 2, 3, 4, 5]
instead of printing each number on its own line.
When I directly append the range to the elements list is it somehow making a list of a list instead of iterated values like it does when using the for?
With a little testing I got this:
>>> print range(1, 6)
[1, 2, 3, 4, 5]
>>> elements = []
>>> elements.append(range(1, 6))
>>> print elements
[[1, 2, 3, 4, 5]]
Is this why it won't let me print the numbers using the %d formatter? How would I un-nest this list or access the contents of it? I'd be very grateful if someone could walk me through this. Thanks!
What's happening when you append a list to another list is that you'll get a nested list. Initially you had elements = []. In that list you appended another list (range(1, 6)) which makes it a list of a list.
>>> elements = []
>>> elements
[]
>>> elements.append(range(1, 6))
>>> elements
[[1, 2, 3, 4, 5]]
What you can do here is concatenate instead of appending by using the + operator (i.e. elements + range(1, 6).
>>> elements = []
>>> elements
[]
>>> elements + range(1, 6)
[1, 2, 3, 4, 5]
Because range(1,6) returns a list. So elements looks like:
[[1, 2, 3, 4, 5]] and the first iteration of your for loop number = elements[0] = [1, 2, 3, 4, 5], which is a list.
If you do this, you will get what you expect:
elements = []
elements = range(1, 6)
for number in elements:
print "Line %d" % numberr
In Python 2.7, range returns a list. And append method adds an item to the end of the list.
So, when you write elements.append(range(1, 6)), elements is now a list with a single element (that is a list).
You may want to use
elements.extend(range(1,6)) # 'extend' append all elements of the given list
Or directly
elements = range(1,6)
Say I have a list of list
X=[[0,0,0,3,4],[8,8,9,2,8,2]]
How do I make it so that each sublist will only contain a repeated number once:
Like this new list:
XNew=[[0,3,4],[8,9,2]]
You can use set for that:
new_x = [list(set(i)) for i in old_x]
Sets are a collection of unique elements and therefore create a set of unique values when a list of duplicate values is cast as a set. You can then convert the set back to a list and get the desired result.
Example
>>> old_x = [[0,0,0,3,4],[8,8,9,2,8,2]]
>>> new_x = [list(set(i)) for i in old_x]
>>> print new_x
[[0,3,4],[8,9,2]]
If you need to keep the order of your numbers, you can't use sets. This would keep the original order:
lst = [[0, 0, 0, 3, 4], [8, 8, 9, 2, 8, 2]]
new_lst = []
for sub_lst in lst:
seen = set()
new_sub = []
for item in sub_lst:
if item not in seen:
new_sub.append(item)
seen.add(item)
new_lst.append(new_sub)
print new_lst # [[0, 3, 4], [8, 9, 2]]
I'm using python 2.7 I'm trying to figure out a way to change the names of my lists automatically.
Let me explain i have multiple lists
list1 = [1, 2, 3, 4, 5]
list2 = [4, 5, 9, 3]
list3 = [8, 4, 3, 2, 1]
I would like to call the lists in a loop to determine which lists contain or do not contain a particular number.
My first thought was
x = "list" + str(i) # (where i iterates in the loop)
print x
However, using the above code only gave me the string "list1"(when i=1).
What I want is to be able to call the list that is named list1 and use the .count() operator to determine whether or not the number exists if it doesn't i want to call the next list until I'm out of lists(there will eventually be up to 30 lists).
Thanks,
Ryan
You shouldn't approach it like this. Put your lists in a container to iterate over them instead:
In [5]: for l in (list1, list2, list3):
...: print l.count(2)
...:
1
0
1
What you could do in a real-life use case is create a list of lists and fill it dynamically.
Then to get the first list that contains a given number, you could do:
In [6]: lists = [list1, list2, list3]
In [7]: next(l for l in lists if 9 in l)
Out[7]: [4, 5, 9, 3]
put the list in dict:
list1 = [1,2.4]
list2 = [2,5,6]
dlist = {1:list1,2:list2}
for k in dlist:
print dlist[k]
So heres my code:
item = [0,1,2,3,4,5,6,7,8,9]
z = [] # list of integers
for item in z:
if item not in z:
print item
z contains a list of integers. I want to compare item to z and print out the numbers that are not in z when compared to item.
I can print the elements that are in z when compared not item, but when I try and do the opposite using the code above nothing prints.
Any help?
Your code is not doing what I think you think it is doing. The line for item in z: will iterate through z, each time making item equal to one single element of z. The original item list is therefore overwritten before you've done anything with it.
I think you want something like this:
item = [0,1,2,3,4,5,6,7,8,9]
for element in item:
if element not in z:
print(element)
But you could easily do this like:
[x for x in item if x not in z]
or (if you don't mind losing duplicates of non-unique elements):
set(item) - set(z)
>> items = [1,2,3,4]
>> Z = [3,4,5,6]
>> print list(set(items)-set(Z))
[1, 2]
Using list comprehension:
print [x for x in item if x not in Z]
or using filter function :
filter(lambda x: x not in Z, item)
Using set in any form may create a bug if the list being checked contains non-unique elements, e.g.:
print item
Out[39]: [0, 1, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print Z
Out[40]: [3, 4, 5, 6]
set(item) - set(Z)
Out[41]: {0, 1, 2, 7, 8, 9}
vs list comprehension as above
print [x for x in item if x not in Z]
Out[38]: [0, 1, 1, 2, 7, 8, 9]
or filter function:
filter(lambda x: x not in Z, item)
Out[38]: [0, 1, 1, 2, 7, 8, 9]
list1 = [1,2,3,4]; list2 = [0,3,3,6]
print set(list2) - set(list1)
If you run a loop taking items from z, how do you expect them not to be in z? IMHO it would make more sense comparing items from a different list to z.
No, z is undefined. item contains a list of integers.
I think what you're trying to do is this:
#z defined elsewhere
item = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
for i in item:
if i not in z: print i
As has been stated in other answers, you may want to try using sets.
>>> item = set([0,1,2,3,4,5,6,7,8,9])
>>> z = set([2,3,4])
>>> print item - z
set([0, 1, 5, 6, 7, 8, 9])
Your code is a no-op. By the definition of the loop, "item" has to be in Z. A "For ... in" loop in Python means "Loop though the list called 'z', each time you loop, give me the next item in the list, and call it 'item'"
http://docs.python.org/tutorial/controlflow.html#for-statements
I think your confusion arises from the fact that you're using the variable name "item" twice, to mean two different things.
You are reassigning item to the values in z as you iterate through z. So the first time in your for loop, item = 0, next item = 1, etc... You are never checking one list against the other.
To do it very explicitly:
>>> item = [0,1,2,3,4,5,6,7,8,9]
>>> z = [0,1,2,3,4,5,6,7]
>>>
>>> for elem in item:
... if elem not in z:
... print elem
...
8
9
In the case where item and z are sorted iterators, we can reduce the complexity from O(n^2) to O(n+m) by doing this
def iexclude(sorted_iterator, exclude_sorted_iterator):
next_val = next(exclude_sorted_iterator)
for item in sorted_iterator:
try:
while next_val < item:
next_val = next(exclude_sorted_iterator)
continue
if item == next_val:
continue
except StopIteration:
pass
yield item
If the two are iterators, we also have the opportunity to reduce the memory footprint not storing z (exclude_sorted_iterator) as a list.
If the lists are sorted and you know the elements of the checking list are in the base list - you can do a more optimal O(n) solution by using two pointers (where n will be the length of the base_list:
base_list = [0, 1, 2, 3, 4, 5, 6, 7, 8]
checking_list = [1, 3, 5]
expected_return = [0, 2, 4, 6, 7, 8]
j = 0
i = 0
elements_not_in_checking_list = []
while i < len(base_list):
if j < len(checking_list) and base_list[i] == checking_list[j]:
i += 1
j += 1
else:
elements_not_in_checking_list.append(base_list[i])
i += 1
Many of the solutions already posted here will not preserve the original ordering of the elements (because sets are unordered) or are inefficient (because linear search in a list is slower than a lookup in a set).
You can make a set of elements to remove upfront, and then use a list comprehension to retain only the elements which aren't in the set:
items = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
z = [3, 4, 5, 6]
set_z = set(z)
result = [e for e in items if e not in set_z]
Then, result contains:
[0, 1, 2, 7, 8, 9]