#python #set
#python #набор
Вопрос:
У меня есть набор строк: {'Type A', 'Type B', 'Type C'}
например, я назову его x
. Набор может содержать до 10 строк.
Существует также большой список наборов, например [{'Type A', 'Type B', 'Type C'}, {'Type A', 'Type B', 'Type C'}, {'Type B', 'Type C, 'Type D'}, {'Type E', 'Type F', 'Type G'}]
, и так далее.
Моя цель — вернуть все наборы в большом списке, которые содержат 60% или более тех же элементов, x
что и . Итак, в этом примере он вернет первые 3 набора, но не 4-й.
Я знаю, что мог бы перебирать каждый набор, сравнивать элементы, а затем использовать количество сходств для своих дел, но это требует довольно много времени, и в моем большом списке, вероятно, будет много наборов. Есть ли лучший способ сделать это? Я думал об их использовании frozenset()
и хешировании, но я не уверен, какую функцию хеширования я бы использовал и как я бы сравнивал хэши.
Любая помощь будет оценена — большое спасибо!
Комментарии:
1. Что вы подразумеваете под «сравнением элементов»? Не могли бы вы просто получить
intersection
из 2 наборов и проверить размер?2. @ScottHunter о, спасибо! Я забыл о пересечениях — я думаю, это должно решить мою проблему,
3.
set
элементы уже хэшированы, поэтому поиск элемента — этоO(1)
операция. При этом ваши основные накладные расходы заключаются в переборе списка, поскольку предполагается, что в нем должно быть много наборов , и хеширование в этом не поможет.
Ответ №1:
l = [{'Type A', 'Type B', 'Type C'}, {'Type A', 'Type B', 'Type C'}, {'Type B', 'Type C', 'Type D'}, {'Type E', 'Type F', 'Type G'}]
x = {'Type A', 'Type B', 'Type C'}
for s in l:
print (len(x.intersection(s)))
Вывод:
3
3
2
0
С возвращением функции и списка кортежей:
def more_than(l,n):
return [ (s,round(len(x.intersection(s))/len(x),2)) for s in l if len(x.intersection(s))/len(x) > n]
print (more_than(l,0.6))
Вывод:
[({'Type B', 'Type A', 'Type C'}, 1.0), ({'Type B', 'Type A', 'Type C'}, 1.0), ({'Type B', 'Type C', 'Type D'}, 0.67)]
Здесь, просто для удобства, я использовал round(len(x.intersection(s))/len(x),2)
which переводится round(x,y)
как . round()
Просто округлит ваше отношение до числа десятичных знаков, указанного с помощью y
переменной.
Комментарии:
1. Обратите внимание, что это приведет только к печати наборов, но не вернет их в списке, как того требует OP. Он также не проверяет пороговое значение (60%).
2. Проверьте редактирование, первым был только принцип
3. @Synthase, не могли бы вы помочь мне выяснить, почему вы использовали 2 в этом наборе. (s, круглый(len(x.пересечение (s))/len(x),2)). Я новичок в python и учусь на других проблемах и на основе приведенных ответов.
4. @Synthase, я бы определенно поставил галочку на кнопку «Принять», но этот вопрос был поднят кем-то другим.
Ответ №2:
Как насчет этого?
x = {'Type A', 'Type B', 'Type C'}
lst = [{'Type A', 'Type B', 'Type C'},
{'Type A', 'Type B', 'Type C'},
{'Type B', 'Type C', 'Type D'},
{'Type E', 'Type F', 'Type G'}]
[s for s in lst if len(s.intersection(x)) > len(x) * 0.6]
Комментарии:
1. Это будет работать быстрее, если вы присвоите
len(x) * 0.6
переменной перед пониманием.