Question

I need to be able to find the first common list (which is a list of coordinates in this case) between a variable amount of lists.

i.e. this list

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

should return

>>> [3,4]

If easier, I can work with a list of all common lists(coordinates) between the lists that contain the coordinates.

I can't use sets or dictionaries because lists are not hashable(i think?).

Was it helpful?

Solution

Correct, list objects are not hashable because they are mutable. tuple objects are hashable (provided that all their elements are hashable). Since your innermost lists are all just integers, that provides a wonderful opportunity to work around the non-hashableness of lists:

>>> lists = [[[1,2],[3,4],[6,7]],[[3,4],[5,9],[8,3],[4,2]],[[3,4],[9,9]]]
>>> sets = [set(tuple(x) for x in y) for y in lists]
>>> set.intersection(*sets)
set([(3, 4)])

Here I give you a set which contains tuples of the coordinates which are present in all the sublists. To get a list of list like you started with:

[list(x) for x in set.intersection(*sets)]

does the trick.

To address the concern by @wim, if you really want a reference to the first element in the intersection (where first is defined by being first in lists[0]), the easiest way is probably like this:

#... Stuff as before
intersection = set.intersection(*sets)
reference_to_first = next( (x for x in lists[0] if tuple(x) in intersection), None ) 

This will return None if the intersection is empty.

OTHER TIPS

If you are looking for the first child list that is common amongst all parent lists, the following will work.

def first_common(lst):
    first = lst[0]
    rest = lst[1:]
    for x in first:
        if all(x in r for r in rest):
            return x

Solution with recursive function. :)

This gets first duplicated element.

def get_duplicated_element(array):
    global result, checked_elements
    checked_elements = []
    result = -1
    def array_recursive_check(array):
        global result, checked_elements
        if result != -1: return
        for i in array:
            if type(i) == list:
                if i in checked_elements:
                    result = i
                    return
                checked_elements.append(i)
                array_recursive_check(i)
    array_recursive_check(array)
    return result

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

you can achieve this with a list comprehension:

>>> l = [[[1,2],[3,4],[6,7]],[[3,4],[5,9],[8,3],[4,2]],[[3,4],[9,9]]]
>>> lcombined =  sum(l, [])
>>> [k[0] for k in [(i,lcombined.count(i)) for i in lcombined] if k[1] > 1][0]
[3, 4]
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top