Форум сайта python.su
Привет всем!
Писал сравнение списков, где важен порядок элементов. Написал:
#!/usr/bin/python3 # -*- coding: UTF-8 -*- import difflib class List: def __init__(self,lst1=[],lst2=[]): if lst1 is None: self.lst1 = [] else: self.lst1 = list(lst1) if lst2 is None: self.lst2 = [] else: self.lst2 = list(lst2) # Find shared elements (strict order), based on 'self.diff' def shared_strict(self): seqm = difflib.SequenceMatcher(a=self.lst1,b=self.lst2) output = [] for opcode, a0, a1, b0, b1 in seqm.get_opcodes(): if opcode == 'equal': output += seqm.a[a0:a1] return output # Check if 'lst1' fully comprises 'lst2' (strict order) def eats_strict(self): if self.lst2 == self.shared_strict(): return True if __name__ == '__main__': lst1 = ['черная','и','белая','кошка'] lst2 = ['белая','кошка'] print(List(lst1,lst2).eats_strict())
>>> lst1 = ['a','b','c','d','e','f','g'] >>> lst2 = ['e','f','g'] >>> lst1.index(lst2) Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: ['e', 'f', 'g'] is not in list >>> lst2 in lst1 False
Офлайн
Наверное потому, что и in, и index ищут элементы, а не последовательности оных.
Другими словами, не логично было бы использовать операторы/функции, от которых все, кроме, возможно, вас, ожидают поиска элемента для поиска последовательностей.
PS. Кстати,
x in some_list
some_list.__contains__(x)
Офлайн
in, и index ищут то, что им говорят, вы говорите найти список lst2 в списке lst1, а в нём нет никаких списков, только строковые элементы. Если в lst1 добавить как элемент lst2, то сразу найдёт:
lst2 = ['e','f','g'] lst1 = ['a','b','c',lst2,'d','e','f','g'] print(lst1.index(lst2)) print(lst2 in lst1)
Офлайн
rami, Slow
Если в lst1 добавить как элемент lst2, то сразу найдётЯсно, спасибо!
Офлайн
Если надо получить ответ “Да” или “Нет” и список содержит только строки (str), то можно преобразовать списки в строки и сравнить их.
rez = False a = ",".join(lst1) b = ",".join(lst2) if b in a: rez = True
Офлайн
Rafik
так нельзя:
>>> lst1 = ['список','содержащий'] >>> lst2 = ['список','с'] >>> a = ",".join(lst1) >>> b = ",".join(lst2) >>> b in a True
Офлайн
например, так:
def index_of_subsequence(container, subsequence): if len(subsequence) > len(container): return None for i in range(len(container) - len(subsequence) + 1): for c_, s_ in zip(container[i:], subsequence): if c_ != s_: break else: return i
Отредактировано Slow (Ноя. 16, 2018 17:06:37)
Офлайн
Slow
Спасибо. В итоге выяснилось, что работа со списками слишком медленная для длинных текстов, поэтому я действительно лучше сначала преобразую список в строку, как советовал Rafik, только добавлю по бокам пробелов, чтобы исключить ненужные совпадения.
Отредактировано vanvanov (Ноя. 16, 2018 18:50:17)
Офлайн
vanvanovНе надо список преобразовывать в строку, это может приводить к редким ошибкам, которые не видны изначально. К тому же список может содержать не только строки, но и элементы произвольных типов, с которыми ты не сможешь сделать .join().
поэтому я действительно лучше сначала преобразую список в строку
>>> lst1 = ['a', ',', 'b', 'c', 'd'] >>> lst2 = [',,b', 'c'] >>> >>> rez = False >>> a = ",".join(lst1) >>> b = ",".join(lst2) >>> >>> if b in a: ... rez = True ... >>> rez True >>>
Отредактировано py.user.next (Ноя. 17, 2018 01:21:29)
Офлайн
py.user.next
Согласен, алгоритм со строками неполноценен. Но у меня для него специфическое применение - только в тексте и без дублирующихся пробелов. Я уже пробовал (и вчера, и год назад) алгоритмы со списками, но везде это слишком долго - 5 мин на 2 текстах суммарно в 22 страницы. Разумеется, везде подряд хак со строками я применять не буду. Возможно, стоит приглядеться к массивам numpy, я не знаю.
Офлайн