У меня есть большой список строк (не более 2k), и я хочу найти наиболее часто встречающееся партичное совпадение в списке. Например, я стараюсь удовлетворительно выполнить следующий тестовый пример.
data = [
'abcdef',
'abcxyz',
'xyz',
'def',
]
result = magic_function(data)
assert result == 'abc'
Я пробовал это с вдохновением из qaru.site/questions/10918744/..., но тот факт, что некоторые элементы в списке полностью разные, отбрасывает его.
def magic_function(data):
return ''.join(c[0] for c in takewhile(lambda x: all(x[0] == y for y in x), zip(*data)))
Вам, вероятно, придется подкорректировать это и проверить его.
Я по существу питаю все частичные подстроки до длины каждого слова в data
в Counter
и создаю ранжирование, основанное на len(substring)*occurence
- наложение штрафов только на 1 путем умножения на 0,1:
data = [
'abcdef',
'abcxyz',
'xyz',
'def',
]
def magic(d):
"""Applies magic(tm) to the list of strings given as 'd'.
Returns a list of ratings which might be the coolest substring."""
from collections import Counter
myCountings = Counter()
def allParts(word):
"""Generator that yields all possible word-parts."""
for i in range(1,len(word)):
yield word[:i]
for part in d:
# count them all
myCountings.update(allParts(part))
# get all as tuples and sort based on heuristic length*occurences
return sorted(myCountings.most_common(),
key=lambda x:len(x[0])*(x[1] if x[1] > 1 else 0.1), reverse=True)
m = magic(data)
print( m ) # use m[0][0] f.e.
Выход:
[('abc', 2), ('ab', 2), ('a', 2), ('abcde', 1), ('abcxy', 1),
('abcd', 1), ('abcx', 1), ('xy', 1), ('de', 1), ('x', 1), ('d', 1)]
Вам нужно будет немного изменить критерии сортировки и использовать только первый в результирующем списке, но вы можете использовать его как стартер.
Тонкая настройка может быть выполнена путем умножения длины на faktor, если вы предпочитаете более длинные из нескольких коротких - это зависит от ваших данных...
data
также будет'ape'
- будет ли'a'
вашей магией? И если нет, то почему?