У меня есть список списков. Списки в этих списках выглядят следующим образом:

[0,2,5,8,7,12,16,18], [0,9,18,23,5,8,15,16], [1,3,4,17,19,6,13,23],
[9,22,21,10,11,20,14,15], [2,8,23,0,7,16,9,15], [0,5,8,7,9,11,20,16]

Каждый маленький список имеет 8 значений от 0 до 23, и в небольшом списке нет повторений значений.

Теперь мне нужны три списка, в которых хранятся значения 0-23. Возможно, что для этого есть пара комбинаций, но мне нужна только одна.

В этом конкретном случае вывод будет:

[0,2,5,8,7,12,16,18], [1,3,4,17,19,6,13,23], [9,22,21,10,11,20,14,15]

Я думал сделать что-то с заказом, но я не профессионал в Python, поэтому мне трудно обрабатывать все списки в списке (сравнивать все).

Спасибо за вашу помощь.

1
Tobias 16 Дек 2015 в 12:50

3 ответа

Лучший ответ

Похоже, что работает следующее:

from itertools import combinations, chain

lol = [[0,2,5,8,7,12,16,18], [0,9,18,23,5,8,15,16], [1,3,4,17,19,6,13,23], [9,22,21,10,11,20,14,15], [2,8,23,0,7,16,9,15], [0,5,8,7,9,11,20,16]]

for p in combinations(lol, 3):
    if len(set((list(chain.from_iterable(p))))) == 24:
        print(p)
        break     # if only one is required

Это отображает следующее:

([0, 2, 5, 8, 7, 12, 16, 18], [1, 3, 4, 17, 19, 6, 13, 23], [9, 22, 21, 10, 11, 20, 14, 15])
5
Martin Evans 16 Авг 2019 в 09:26

Давайте сделаем рекурсивное решение.

Нам нужен список списков, которые содержат эти значения:

target_set = set(range(24))

Это функция, которая рекурсивно пытается найти список списков, которые точно соответствуют этому набору:

def find_covering_lists(target_set, list_of_lists):
    if not target_set:
        # Done
        return []

    if not list_of_lists:
        # Failed
        raise ValueError()

    # Two cases -- either the first element works, or it doesn't
    try:
        first_as_set = set(list_of_lists[0])
        if first_as_set <= target_set:
            # If it's a subset, call this recursively for the rest
            return [list_of_lists[0]] + find_covering_lists(
                target_set - first_as_set, list_of_lists[1:])
    except ValueError:
        pass  # The recursive call failed to find a solution

    # If we get here, the first element failed.
    return find_covering_lists(target_set, list_of_lists[1:])
0
RemcoGerlich 16 Дек 2015 в 10:30

Если всегда будет так, что список 3 будет формировать числа от 0 до 23, и вам нужен только первый список, то это можно сделать, создав комбинации длины 3, а затем установите пересечение:

>>> li = [[0,2,5,8,7,12,16,18], [0,9,18,23,5,8,15,16], [1,3,4,17,19,6,13,23], [9,22,21,10,11,20,14,15], [2,8,23,0,7,16,9,15], [0,5,8,7,9,11,20,16]]

>>> import itertools
>>> for t in itertools.combinations(li, 3):
...     if not set(t[0]) & set(t[1]) and not set(t[0]) & set(t[2]) and not set(t[1]) & set(t[2]):
...         print t
...         break
([0, 2, 5, 8, 7, 12, 16, 18], [1, 3, 4, 17, 19, 6, 13, 23], [9, 22, 21, 10, 11, 20, 14, 15])
3
Rohit Jain 16 Дек 2015 в 11:02