Grouping together items that appear together in separate list

Viewed 113

I have 2 nested lists and I want to write some code that will run through each sub-list in both lists, and group together any elements that appear together in both lists. The project I am working on actually has huge nested lists, so I have created the following 2 lists to simplify the problem a little (I only have a year of experience in python). If a function can be made that groups together elements in these 2 lists, I can then apply the function to the actual project. This question may be similar to: Find items that appear together on multiple lists, but I could not understand the code written in that question, and as I said, I'm relatively new to python.

my_list = [['a', 'd', 'l'], ['c', 'e', 't'], ['q', 'x'], ['p', 'f', 'd', 'k']

sec_list = [['f', 'd', 'w', 'a'], ['c', 'e', 'u', 'h'], ['q', 'x', 'd', 'z'], ['p', 'k']]

##The output should be something like:

[['a', 'd'], ['c', 'e'], ['q', 'x'], ['p', 'k'], ['f', 'd']]```

Thanks
3 Answers

You can use zip to iterate over two sequences and find common elements with set intersection. Note that your code is missing a closing ] in my_list

my_list = [['a', 'd', 'l'], ['c', 'e', 't'], ['q', 'x'], ['p', 'f', 'd', 'k']]
sec_list = [['f', 'd', 'w', 'a'], ['c', 'e', 'u', 'h'], ['q', 'x', 'd', 'z'], ['p', 'k']]

# each item of my_list and sec_list are lists
# zip allows parallel iteration so l1 and l2 are the pairs of inner lists
# sets are designed for tasks like finding common elements
# the & sign is python for set intersection 
matches = []
for l1, l2 in zip(my_list, sec_list):
    matches.append(list(set(l1) & set(l2)))

this can be consolidated into a list comprehension

my_list = [['a', 'd', 'l'], ['c', 'e', 't'], ['q', 'x'], ['p', 'f', 'd', 'k']]
sec_list = [['f', 'd', 'w', 'a'], ['c', 'e', 'u', 'h'], ['q', 'x', 'd', 'z'], ['p', 'k']]
matches = [list(set(l1) & set(l2)) for l1, l2 in zip(my_list, sec_list)]

If you want to keep duplicates, you can use this solution using collections.Counter:

from collections import Counter

my_list = [['a', 'd', 'l'], ['c', 'e', 't'], ['q', 'x'], ['p', 'f', 'd', 'k', 'k']]

sec_list = [['f', 'd', 'w', 'a'], ['c', 'e', 'u', 'h'], ['q', 'x', 'd', 'z'], ['p', 'k', 'k']]

    
result = [list((Counter(a) & Counter(b)).elements()) for a in my_list for b in sec_list]
result = [x for x in result if len(x) > 0]
    
print(result)

Output:

[['a', 'd'], ['d'], ['c', 'e'], ['x', 'q'], ['f', 'd'], ['d'], ['k', 'k', 'p']]                                                                                                                                                                                                         

Update based on comments.

Based on the comments:

my_list = [["a", "d", "l"], ["c", "e", "t"], ["q", "x"], ["p", "f", "d", "k"]]
sec_list = [
    ["f", "d", "w", "a"],
    ["c", "e", "u", "h"],
    ["q", "x", "d", "z"],
    ["p", "k"],
]

# to speed up, convert the sublists to sets
tmp1 = [set(i) for i in my_list]
tmp2 = [set(i) for i in sec_list]

out = []
for s1 in tmp1:
    for s2 in tmp2:
        m = s1 & s2
        if m:
            out.append(list(m))
print(out)

Prints:

[['d', 'a'], ['d'], ['e', 'c'], ['x', 'q'], ['d', 'f'], ['d'], ['k', 'p']]
Related