I am a beginner in Python and am trying to solve the List Overlap problem on Practice Python.
I have written some code for solving this but the code seems to have a mind of its own. It works sometimes and at other times it just returns a blank. Where am I going wrong?
lista= map(int,input('Enter a list of numbers separated by spaces :').split())
listb= map(int,input('Enter another list of numbers separated by spaces :').split())
listc=[]
for item in lista:
if item in listb:
listc.append(item)
print(listc)
After running:
Enter a list of numbers separated by spaces :1 3 5
Enter another list of numbers separated by spaces :3 7 9
[] <-- unexpected result- I was hoping to see a new list with [3] in it.
The strange behavior you're experiencing has to do with how the map
function works in Python 3. You might be expecting that it returns a list as it does in Python 2 which can be repeatedly queried with the in
keyword. In Python 3, however, map
returns an iterator, which is an object that implements the __next__
method, enabling the mapped function to be applied lazily (but can only be traversed once). Using the in
keyword on an iterator will exhaust it and harm accuracy of future in
calls:
>>> map(int, ["1", "2", "3"])
<map object at 0x027FF5D0>
>>> it = map(int, ["1", "2", "3"])
>>> 1 in it
True
>>> 1 in it
False
>>> 1 in it
False
Had your example been something like 1 2 3
and 1 2 3
, it'd appear to work because the iterator would find 1
in listb
and pause, find 2
and pause, then find 3
and pause, exhausting both iterators together. But 1 3 5
, 3 7 9
fails because the listb
iterator is exhausted searching for 1
and returns false for any future in
operations.
The solution is to explicitly convert the iterator returned by map
into a list:
>>> list(map(int, ["1", "2", "3"]))
[1, 2, 3]
or use a list comprehension, which returns a list and effectively works as a map, applying a function to every element of the input list:
>>> [int(x) for x in ["1", "2", "3"]]
[1, 2, 3]
With this change, the code should work as expected. Note that making lista
a list isn't strictly necessary since it's only traversed once (but the name suggests that you'd like it to be a list):
lista = list(map(int, input('Enter a list of numbers separated by spaces :').split()))
listb = list(map(int, input('Enter another list of numbers separated by spaces :').split()))
# ^^^^
listc = []
for item in lista:
if item in listb:
listc.append(item)
print(listc)
Sample run:
Enter a list of numbers separated by spaces: 1 3 5
Enter a list of numbers separated by spaces: 3 7 9
[3]
For further reading on iterables and iterators, see: What exactly are iterator, iterable, and iteration?.
Having gone through this, note that your code doesn't account for duplicates correctly, so you'll still fail the coding challenge you're attempting. See if you can manipulate your logic to check if the value isn't already in listc
before adding. Once you've successfully finished the challenge using lists, try exploring the set
data structure, as others have mentioned, which offers a semantic and efficient way of accomplishing intersection.