#python #string #set #max
#python #строка #набор #макс
Вопрос:
У меня есть список (str,int)
пар
list_word = [('AND', 1), ('BECAUSE', 1), ('OF', 1), ('AFRIAD', 1), ('NEVER', 1), ('CATS', 2), ('ARE', 2), ('FRIENDS', 1), ('DOGS', 2)]
Это в основном говорит о том, сколько раз каждое слово появлялось в тексте.
Я хочу получить набор слов с максимальным вхождением и максимальным числом вхождений. Итак, в приведенном выше примере я хочу получить
(set(['CATS', 'DOGS','ARE']), 2)
Решение, о котором я могу думать, — это перебор списка. Но есть ли какой-нибудь элегантный способ сделать это?
Комментарии:
1. Вызов вашей переменной
list
может быть опасным.2. Ах, спасибо, что указали. Я просто писал здесь для большей ясности. Редактирование сейчас
Ответ №1:
Два линейных сканирования, сначала для поиска максимального элемента:
maxcount = max(map(itemgetter(1), mylist))
затем секунда, чтобы извлечь нужные вам значения:
maxset = {word for word, count in mylist if count == maxcount}, maxcount
Если вам нужно было получить наборы не только для максимального количества, вы можете использовать collections.defaultdict
для накопления по количеству за один проход:
from collections import defaultdict
sets_by_count = defaultdict(set)
for word, count in mylist:
sets_by_count[count].add(word)
За которым затем можно следовать, allcounts = sorted(sets_by_count.items(), key=itemgetter(0), reverse=True)
чтобы получить list
количество count, set
пар, от наивысшего до наименьшего количества (с минимальной сортировкой, поскольку сортируется только количество элементов, равное количеству уникальных значений, а не все слова).
Ответ №2:
Преобразовать list
в dict
с ключом в качестве числа и значением в виде набора слов. Найдите max
значение ключа и соответствующее ему значение
from collections import defaultdict
my_list = [('AND', 1), ('BECAUSE', 1), ('OF', 1), ('AFRIAD', 1), ('NEVER', 1), ('CATS', 2), ('ARE', 2), ('FRIENDS', 1), ('DOGS', 2)]
my_dict = defaultdict(set)
for k, v in my_list:
my_dict[v].add(k)
max_value = max(my_dict.keys())
print (my_dict[max_value], max_value)
# prints: (set(['CATS', 'ARE', 'DOGS']), 2)
Ответ №3:
Хотя более питонические решения, безусловно, проще на глаз, к сожалению, требование двух сканирований или построения структур данных, которые вам на самом деле не нужны, значительно медленнее.
Следующее довольно скучное решение примерно на ~ 55% быстрее, чем решение dict, и на ~ 70% быстрее, чем решения, основанные на понимании, основанные на предоставленных примерах данных (и моих реализациях, машине, бенчмаркинге и т. Д.)
Это почти наверняка сводится к одному сканированию здесь, а не к двум.
word_occs = [
('AND', 1), ('BECAUSE', 1), ('OF', 1), ('AFRIAD', 1), ('NEVER', 1),
('CATS', 2), ('ARE', 2), ('FRIENDS', 1), ('DOGS', 2)
]
def linear_scan(word_occs):
max_val = 0
max_set = None
for word, occ in word_occs:
if occ == max_val:
max_set.add(word)
elif occ > max_val:
max_val, max_set = occ, {word}
return max_set, max_val
Честно говоря, все они работают очень быстро, и в вашем случае удобочитаемость может быть более важной.