Поиск совпадения из списка кортежей - PullRequest
1 голос
/ 17 апреля 2020

У меня есть список кортежей, как показано ниже.

x = [('b', 'c'),
 ('c',),
 ('a', 'c', 'b'),
 ('b', 'c', 'a', 'd'),
 ('b', 'c', 'a'),
 ('a', 'b'),
 ('a', 'b', 'c', 'd'),
 ('a', 'c', 'b', 'd'),
 ('b',),
 ('c', 'a'),
 ('a', 'b', 'c'),
 ('a',)]

Я хочу дать ввод как ('a'), тогда он должен дать вывод как,

[('a', 'c', 'b'), ('a', 'b'),('a', 'b', 'c', 'd'),('a', 'c', 'b', 'd'),('a', 'b', 'c')]
#everything starts with a. But not "a".

или для ввода ('a', 'b') этого должен выдать вывод

[('a', 'b', 'c', 'd'),('a', 'b', 'c')]
#everything start with ('a','b') but not ('a','b') itself.

Я пытался использовать, но безуспешно.

   print(filter(lambda x: ("a","b") in x, x))
>>> <filter object at 0x00000214B3A545F8>

Ответы [ 5 ]

5 голосов
/ 17 апреля 2020
def f(lst, target):
    return [t for t in lst if len(t) > len(target) and all(a == b for a, b in zip(t, target))]

так что:

f(x, ('a', 'b'))

возвращает:

[('a', 'b', 'c', 'd'), ('a', 'b', 'c')]
3 голосов
/ 17 апреля 2020

Кортежи сопоставляются лексикографически в python, что означает, что элементы сравниваются попарно, независимо от их типа.

Вы можете извлечь часть каждого кортежа той же длины, что и ваш префикс, и сравнить с ==:

def find_prefixes(prefix, sequence):
    n = len(prefix)
    return[x for x in sequence if x[:n] == prefix and len(x) > n]

Постижения списка этого типа действительно эквивалентны filter вызовам, поэтому вы можете сделать

def find_prefixes(prefix, sequence):
    n = len(prefix)
    return list(filter(lambda x: x[:n] == prefix and len(x) > n, sequence))

Выполнение линейного поиска не очень эффективно способ решить эту проблему. Структура данных, известная как Tr ie, создана специально для поиска префиксов. Он организует все ваши данные в одно дерево. Вот популярная Python реализация, которую вы можете использовать с соответствующей атрибуцией: { ссылка }

1 голос
/ 17 апреля 2020

Во-первых, используйте list(filter(...)) для преобразования объекта фильтра в список, но ваш фильтр не делает то, что вы хотите - он проверяет членство, а не подпоследовательность. Вы можете проверить подпоследовательность, используя срез.

Тогда вам просто нужно добавить проверку того, что совпадение длиннее подпоследовательности.

Кроме того, фильтр лямбды лучше записать как понимание.

for sub in ('a',), ('a', 'b'):
    n = len(sub)
    out = [t for t in x if t[:n] == sub and len(t) > n]
    print(out)

Вывод:

[('a', 'c', 'b'), ('a', 'b'), ('a', 'b', 'c', 'd'), ('a', 'c', 'b', 'd'), ('a', 'b', 'c')]
[('a', 'b', 'c', 'd'), ('a', 'b', 'c')]
0 голосов
/ 17 апреля 2020
list(filter(lambda y: all([y[i] == z for i,z in enumerate(inp)]) if len(y)>=len(inp) else False, x))

для вывода inp = ('a', 'b') будет

[('a', 'b'), ('a', 'b', 'c', 'd'), ('a', 'b', 'c')]
0 голосов
/ 17 апреля 2020
def starts_with(tup, lst):  # tup is ("a", "b"), for example
    matching = []
    for element in lst:
        if not isinstance(element, tuple):  # Skip elements like "a"
            continue

        if not len(element) > len(tup):  # Don't match ("a", "b") with ("a", "b")
            continue

        if element[:len(tup)] == tup:  # Only match elements that start with tup
            matching.append(element)

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