1

I have two lists:

a = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
b = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]

Need to find the overlapping elements

I am doing my homework.

  if (a[i]==b[i]):
    print(i)```

But I got this error:
IndexError: list index out of range,


I expect result:
1 , 2 , 3 , 5 , 8 , 13
555
  • 147
  • 8
  • 3
    Try using [`sets`](https://docs.python.org/2/library/sets.html) – yatu May 21 '19 at 10:17
  • `list a` has less elements than `list b`, that's why you are getting Index error – rock321987 May 21 '19 at 10:18
  • `print(set(a).intersection(set(b)))` – Rakesh May 21 '19 at 10:19
  • if list b has 2 values for 1 i.e. `b = [1, 1, 2, 3]` would you expect your final list to be `[1, 2, 3]` or `[1, 1, 2, 3]` ? – Alan Kavanagh May 21 '19 at 10:24
  • 1
    Question was closed before I could answer, so just to add (a) it is possible to do this without sets (b) Others have correctly pointed out that the index error is because your lists are different lengths. However, the problem is much deeper than that. The fundamental mistake you made is to compare elements IN THE SAME POSITION. Intersection doesn't care about order (which is also incidently WHY sets are better than lists here). – Neil May 21 '19 at 10:29
  • 1
    Are you sure you understand the problem? What is "overlap" supposed to mean? You could interpret the task as finding matching elements, i.e., cases where the nth element of `a` has the same value as the nth element of `b`. You could interpret the task as finding common elements, i.e, values that are found in both lists. But if it's the latter, how come `a` has the number 1 appearing twice (aside from the fact that `a` happens to be the Fibonacci numbers). – Paul Cornelius May 21 '19 at 10:32
  • Actually good point @PaulCornelius it's not clear whether this is even intersection. Perhaps a premature marking as duplicate? – Neil May 21 '19 at 10:36

2 Answers2

3

You got this error because one list is longer than the other. To solve this problem you can simply convert the lists to sets to eliminate duplicates, and then use the intersection:

a = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
b = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]

list(set(a) & set(b))
# >> [1, 2, 3, 5, 8, 13]
dome
  • 820
  • 7
  • 20
  • What if there are duplicate elements in the overlap? – tobias_k May 21 '19 at 10:22
  • There cannot be, `set(a)` and `set(b)` doesn't have duplicates because they are `set`, therefore also the `intersection` will not have duplicates. – dome May 21 '19 at 10:24
  • That's exactly my point. It's not clear from OP's example, but at least they show that the lists can have duplicates. So what if `a = [1,1,2], b = [1,1,3]`? I think the "overlap" should then be `[1,1]`, but yours will just yield `[1]`. – tobias_k May 21 '19 at 10:33
  • I understood what you mean, but if look at the expexted result of @555, you will see that my solution is what he need. – dome May 21 '19 at 10:40
  • How do you know? None of the numbers in the expected result appear more than once in _both_ lists. – tobias_k May 21 '19 at 10:57
  • Yes, `1` appear two times in list `a`. – dome May 21 '19 at 11:13
  • Yes, but 1 appears just once in `b`, so _in this example_ the correct "overlap" contains 1 just once. But what if `b` _also_ had two 1s? – tobias_k May 21 '19 at 11:31
  • Ok, I understood. In this case my solution wouldn't work. To solve you can do something with a double `for` loop or maybe use `Counter` in some way. – dome May 21 '19 at 11:48
2
a = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
b = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]

print(set(a).intersection(set(b)))
# output {1, 2, 3, 5, 8, 13}

when there are more than 1 occurrence of elements in the list

a = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
b = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,2]

from collections import defaultdict

dic=defaultdict(int)
dic2=defaultdict(int)

for i in a:
    dic[i]+=1
for i in b:
    dic2[i]+=1

l=list(set(a) & set(b))

solution = [j for i in l for j in [i]*min(dic[i],dic2[i])]
print(solution)
# output [1, 2, 3, 5, 8, 13]
sahasrara62
  • 10,069
  • 3
  • 29
  • 44
  • 1
    Or using `collections.Counter`: `[x for x, c in (Counter(a) & Counter(b)).items() for _ in range(c)]` – tobias_k May 21 '19 at 11:33