0

This is the same question as: Common elements comparison between 2 lists but I'm asking for several lists instead of two. From several lists, I want all the elements they all contain to be transferred to a new list.

Ethan Cha
  • 15
  • 3
  • 1
    Just perform it repeatedly for each list. – Barmar Nov 08 '19 at 21:05
  • Can you please be more clear? Do you want the common elements to be in _every_ list or just at least two? – andrewgazelka Nov 08 '19 at 21:06
  • What's the desired output for `list1 = [1,2,3,3,4,5] list2 = [2,3,3,4,5,6] list3 = [3,3,4,5,6,7]`? – Ruzihm Nov 08 '19 at 23:05
  • Does this answer your question? [Common elements comparison between 2 lists](https://stackoverflow.com/questions/2864842/common-elements-comparison-between-2-lists) – Makyen Nov 10 '19 at 23:52

2 Answers2

3

Assuming the order of the elements in the output doesn't matter...

Convert each list to a set then run set.intersection on them. You can use list comprehension and argument expansion to do this in one line:

list1 = [1,2,3,4,5]
list2 = [2,3,4,5,6]
list3 = [3,4,5,6,7]

listoflists = [list1,list2,list3]

commons = list(set.intersection(*[set(l) for l in listoflists]))
print (commons)
[3, 4, 5]

For a little more efficiency, you can call intersection individually:

list1 = [1,2,3,4,5]
list2 = [2,3,4,5,6]
list3 = [3,4,5,6,7]

listoflists = [list1,list2,list3]

commons = set(listoflists[0])
if (len(listoflists)>1):
    for l in listoflists[1:]:
        commons = commons.intersection(l)

This had some better timing for me with long lists that need not be searched completely. Definitely room for improvement here:

import timeit

setups = """
list1 = [1,2]
list2 = [3,4]
list3 = list(range(5000))
list3 = list(range(5001))
list4 = list(range(20000))
listoflists1 = [list1,list2,list3]
listoflists2 = [list1,list2,list3,list4]
"""

test2= """
commons = set(listoflists2[0])
for l in listoflists2[1:]:
    commons = commons.intersection(l)
"""

result = timeit.timeit(setup=setups, number=5000, stmt="list(set.intersection(*(set(l) for l in listoflists1)))")
print("one liner with small exclusive lists and one large: %s" % result)
result = timeit.timeit(setup=setups, number=5000, stmt=test2)
print("loop with more large lists: %s" % result)
result = timeit.timeit(setup=setups, number=5000, stmt="list(set.intersection(*(set(l) for l in listoflists2)))")
print("one liner with more large lists: %s" % result)
one liner with small exclusive lists and one large: 0.8411386758089066 
loop with more large lists: 2.130048044025898 
one liner with more large lists: 4.127526797354221
Community
  • 1
  • 1
Ruzihm
  • 19,749
  • 5
  • 36
  • 48
  • this will fail when frequency of common element is more the 1 in all list, so i think better approach would be sort out all the list according to size in a main list,(not make a main list but reference for order of each list) and the get the common element from smallest 2 list and keep checking those common element and elimination of uncommon or different frequency element – sahasrara62 Nov 08 '19 at 22:44
  • @temmo please explain? `listoflists=[['this','this','n','that'],['this','not','that','that']]` seems to produce `['this','that']` -- the desired output verbatim -- or sometimes `['that','this']`. The different ordering isn't because of the frequency of occurrence of the common element... – Ruzihm Nov 08 '19 at 22:57
  • take this as input `list1 = [1,2,3,3,4,5] list2 = [2,3,3,4,5,6] list3 = [3,3,4,5,6,7]` output should be 3 3 4 5 – sahasrara62 Nov 08 '19 at 22:59
  • @temmo Okay, and it produces `[3,4,5]` for me. Might be in a different order if I run it enough. Seems exactly in line with the `>>> common_elements(['this','this','n','that'],['this','not','that','that']) ['this', 'that']` example from the original question, unless I'm missing something. – Ruzihm Nov 08 '19 at 23:02
  • @temmo Oh, I suppose I see what you're getting at. I don't think that's what asker wants, but I've asked them to clarify. Still, isn't that what your answer outputs as well? – Ruzihm Nov 08 '19 at 23:08
  • your answer is correct for the OP requirement where he want the common elements, i am just considering the account of if the occuerence is more than one. also you are right since OP has not clearly given full description of question it is wrong to say what is right what is wrong – sahasrara62 Nov 08 '19 at 23:55
0

using hashing it can be done this way.

# your code goes here


list1 = [1,2,3,4,5]
list2 = [2,3,4,5,6]
list3 = [3,4,5,6,7]


from collections import defaultdict

dic = defaultdict(int)

al_list = [list1,list2, list3]
al_list = [set(element) for element in al_list]

for sublist in al_list:
        for element in sublist:
            dic[element] +=1

len_list = len(al_list)
common_element = [k for k, v in dic.items() if v==len_list]
print(common_element)

output

 [3, 4, 5]
sahasrara62
  • 10,069
  • 3
  • 29
  • 44
  • yes you are right on this one, what we can do more is make the `al_list` according to the size from small to large and then, we need to find the common elements between the first two and then check if these element are present in the other list, thus will save us more process, get the common element from first 2 list and eliminate these element if they are nnot present in subsequent sublist – sahasrara62 Nov 08 '19 at 22:43