Python: получение всех пар и частоты пар в многомерном списке - PullRequest
1 голос
/ 01 июня 2019

мой многомерный список выглядит следующим образом:

    mylist = [[13, 41, 3, 23, 12, 16], [12, 32, 30, 49, 3, 18], 
              [34, 12, 14, 24, 35, 20], [29, 28, 12, 44, 13, 4],
              [31, 44, 6, 49, 5, 39]]

В некоторых списках есть пары (числа с разницей 1). не в каждом списке: (12,13) ​​в первом списке, (34,35) в третьем списке, (28,29) и (12,13) ​​в четвертом.

Я хочу получить все найденные пары, которые должны быть сохранены в (отсортированном) списке на основе частоты (по возрастанию). В моем случае выше, это будет выглядеть следующим образом:

    fr_list = [[12,13],[12,13],[28,29],[34,35]]

Я написал следующий код, чтобы найти пары

    def find_pairs(lst, key):
            return [(a,b) for a,b in permutations(lst, 2) if a-b==key]

Затем я попробовал это:

    fr_list = [find_pairs(mylist,1) for x in mylist]

Однако я получаю следующее сообщение об ошибке:

    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "<stdin>", line 1, in <listcomp>
      File "<stdin>", line 2, in find_pairs
      File "<stdin>", line 2, in <listcomp>
    TypeError: unsupported operand type(s) for -: 'list' and 'list'

Кто-нибудь может мне помочь? Благодаря.

Ответы [ 4 ]

2 голосов
/ 01 июня 2019

Ваш код является функционально правильным, но ваше окончательное понимание списка неверно. Это должно быть fr_list = [find_pairs(x,1) for x in mylist]. В вашем случае вы пытаетесь поместить список списков в функцию find_pairs. Однако изменение mylist на x означает, что вы перебираете каждый вложенный список, а не весь список списков для каждого вложенного списка.

1 голос
/ 01 июня 2019

Вы, вероятно, должны использовать сортировку, чтобы избежать сравнения каждой пары со всеми другими парами, и collections Counter, чтобы агрегировать результаты:

Может быть, что-то вроде этого:

from collections import Counter

def find_pairs(seq):
    s = sorted(seq)
    all_pairs = []
    for first, second in zip(s[:-1], s[1:]):
        if second - first == 1:
            all_pairs.append((first, second))
    return all_pairs

mylist = [[13, 41, 3, 23, 12, 16], [12, 32, 30, 49, 3, 18], 
              [34, 12, 14, 24, 35, 20], [29, 28, 12, 44, 13, 4],
              [31, 44, 6, 49, 5, 39]]

all_pairs = []
for seq in mylist:
    all_pairs += find_pairs(seq)
res = []
for pair, qtty in sorted([(k, v) for k, v in Counter(all_pairs).items()], key=lambda x: x[1])[::-1]:
    for _ in range(qtty):
        res.append(pair)

res

Выход:

[(12, 13), (12, 13), (5, 6), (28, 29), (34, 35)]
1 голос
/ 01 июня 2019

Вот как бы я поступил так:

from collections import Counter
from itertools import repeat, chain

def find_diff(lst):
    srt = sorted(lst)
    return Counter((a, b) for a, b in zip(srt, srt[1:]) if b - a == 1)

pairs = sum((find_diff(item) for item in mylist), Counter())
# Counter({(12, 13): 2, (34, 35): 1, (28, 29): 1, (5, 6): 1})
res = tuple(
    chain.from_iterable(repeat(item, count) for item, count in pairs.most_common())
)
# ((12, 13), (12, 13), (34, 35), (28, 29), (5, 6))

более эффективно перебирать отсортированный список, если вы ищете разницу 1.затем я сохраняю все в Counter объектах, чтобы эффективно найти наиболее распространенные.

последняя часть - это немного магии itertools, которая извлекаетпредметы и их кратность по частоте.

1 голос
/ 01 июня 2019

Вы ошиблись здесь:

[find_pairs(mylist, 1) for x in mylist]

Вы каждый раз передавали один и тот же исходный список функции, а не подспискам. Следовательно, внутри функции, когда вы делаете if a-b==key, a и b, списки.

Исправляя это, вы можете использовать следующий код для получения желаемого результата:

from itertools import permutations, chain

def find_pairs(lst, key):
    return [(a, b) for a, b in permutations(lst, 2) if a - b == key]


mylist = [[13, 41, 3, 23, 12, 16], [12, 32, 30, 49, 3, 18], 
          [34, 12, 14, 24, 35, 20], [29, 28, 12, 44, 13, 4],
          [31, 44, 6, 49, 5, 39]]


temp_list = list(chain.from_iterable([find_pairs(x, 1) for x in mylist])) 
fr_list = sorted(temp_list, key=lambda x: temp_list.count(x), reverse=True)

print(fr_list)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...