13

I have a list of an arbitrary number of lists, for instance:

[[1,2,3], [3,4,5], [5,6,7], [7,8,9]]

Now I would like a list containing all elements that are present in more than one list:

[3,5,7]

How would I do that?

Thanks!

12 Answers 12

17

The same way as you'd do it by hand:

seen = set()
repeated = set()
for l in list_of_lists:
  for i in set(l):
    if i in seen:
      repeated.add(i)
    else:
      seen.add(i)

By the way, here's the one liner (without counting the import) that some people were seeking (should be less efficient than the other approach)

from itertools import *
reduce(set.union, (starmap(set.intersection, combinations(map(set, ll), 2))))
Sign up to request clarification or add additional context in comments.

5 Comments

Just be careful, as l needs also to be 'setted', or you'll get false positives in [[1,1],[2,2]]
as @Khelben says you should change for i in l: in for i in set(l):
With @Khelben's correction applied that solution worked well. Thanks!
@Khelben thanks for pointing out, I was already thinking in "set mode" instead of lists ^_^
I like the approach. One might want to wrap it into a function for easier use.
8

This only finds elements common to all lists (i.e, the intersection):

 set.intersection(*[set(list) for list in list_of_lists])

3 Comments

this returns empty set when i plug in the original list [[1,2,3], [3,4,5], [5,6,7], [7,8,9]] i think its meant as a intersection of all lists ?
I haven't invested much time in it, but it is not the solution to the OPs question.
I've updated the answer to clarify that it only finds the intersection.
7

Cleanest way would probably be to use reduce:

def findCommon(L):
    def R(a, b, seen=set()):
        a.update(b & seen)
        seen.update(b)
        return a
    return reduce(R, map(set, L), set())

result = findCommon([[1,2,3], [3,4,5], [5,6,7], [7,8,9]])

Result is a set, but just do list(result) if you really need a list.

3 Comments

@Dyno the seen variable contains a "hidden" mutable state between calls... functional programming shouldn't rely on side effects (and it's a peril if they are not explicit, I bet that most of people wouldn't notice that seen is playing the role of a "static" variable instead of a regular argument)
@fortran: The typical usage of functions such as R is one-time, since they are placed inside another function and not at module level. I'll update the answer to make that clearer.
I know that, but even with that premises an incautious reader could be fooled... I think it would be cleaner to move seen outside the parameter list of R and make it a local variable of findCommon.
3

Try this:

data = [[1,2,3], [3,4,5], [5,6,7], [7,8,9], [1,2,3]]

res = set()

for i in data:
    for j in data:
        if i is not j:
            res |= set(i) & set(j)

print res

Comments

3
>>> sets = [[1,2,3], [3,4,5], [5,6,7], [7,8,9]]
>>> seen = set()
>>> duplicates = set()
>>> 
>>> for subset in map(set, sets) :
...     duplicates |= (subset & seen)
...     seen |= subset
... 
>>> print(duplicates)
set([3, 5, 7])
>>> 

I tried for a one-line answer with map/reduce, but can't quite get it yet.

Comments

3

reference: http://docs.python.org/library/stdtypes.html#set

#!/usr/bin/python

ll = [[1,2,3], [3,4,5], [5,6,7], [7,8,9]]
ls = [set(l) for l in ll]

su = ls[0]  #union
ssd = ls[0] #symmetric_difference
for s in ls[1:]:
  su = su.union(s)
  ssd = ssd.symmetric_difference(s)

result = su.difference(ssd)
print list(result)

=>

[3, 5, 7]

revise and adopt FP,

ll = [[1,2,3], [3,4,5], [5,6,7], [7,8,9]]

u = reduce(set.union, map(set, ll))
sd = reduce(set.symmetric_difference, map(set, ll))
print u - sd

=>

[3, 5, 7]

2 Comments

Actually your solution is not correct with my test case like lst_of_lst=[[65L, 66L, 81L, 95L, 96L, 128L, 171L, 193L, 218L, 304L, 305L, 338L, 353L, 355L, 357L, 412L], [86L, 98L, 154L, 356L], [75L, 154L], [38L, 57L, 65L, 145L, 175L, 264L, 325L, 420L, 429L, 439L], [75L, 161L], [66L, 109L, 128L, 137L, 142L, 154L, 183L, 184L, 187L, 203L, 233L, 285L, 289L, 343L]] the result should be [128L, 65L, 66L, 154L, 75L],but your solution miss 154L
@LancelotHolmes Your syntax is invalid. Also, in Python all integers are Long integers...
1

You can use a dictionary to get the count of each

from collections import defaultdict

init_list = [[1,2,3], [3,4,5], [5,6,7], [7,8,9]]
#defaultdict, every new key will have a int(0) as default value
d = defaultdict(int)
for values in init_list:
  #Transform each list in a set to avoid false positives like [[1,1],[2,2]]
  for v in set(values):
    d[v] += 1

#Get only the ones that are more than once
final_list = [ value for value,number in d.items() if number > 1 ]

1 Comment

@muhuk. Yes! you're absolutely right! I've changed the code. The standard library of Python is really big and full of useful things...
1

I am still learning but would like to share my answer.

num_list1 = ['3', '6', '5', '8', '33', '12', '7', '4', '72', '2', '42', '13']
num_list2 = ['3', '6', '13', '5', '7', '89', '12', '3', '33', '34', '1', '344', '42']

result = [int(num) for num in num_list1 if num in num_list2)
print(result)

This prints:

[3, 6, 5, 33, 12, 7, 42, 13]

Comparing all elements in both lists and creating a new list with similar elements. And turning them into integers.

Comments

0
l=[[1,2,3], [3,4,5], [5,6,7], [7,8,9]]
d={}
for x in l:
    for y in x:
        if not d.has_key(y):
            d[y]=0
        d[y]+=1
[x for x,y in d.iteritems() if y>1]

Comments

0

Here is my go:

seen = set()
result = set()
for s in map(set, [[1,2,3], [3,4,5], [5,6,7], [7,8,9]]):
    result.update(s & seen)
    seen.update(s)
print result

This prints:

set([3, 5, 7])

Comments

-2

You can use a set see http://docs.python.org/library/stdtypes.html#set

Comments

-4

flatten, sort, 1 for loop comparing numbers before and after

2 Comments

This would fail if a number occurs twice in the same list.
If you flatten first, you would get a "false positive" on input such as: [[1, 1], [2, 2]]

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.