суммирование количества дубликатов во вложенном списке кортежей

#python #nested #tuples

#python #вложенный #кортежи

Вопрос:

У меня есть список кортежей, который выглядит следующим образом :

 [(('review', 'shop', 'draw'), 35),
 (('shop', 'drawing', 'review'), 32),
 (('field', 'review', 'report'), 24),
 (('review', 'shop', 'drawing'), 20),
 (('shop', 'drawing', 'return'), 20),
 (('shop', 'draw', 'review'), 18),
 (('site', 'review', 'report'), 17),
 (('respond', 'rfi', 'regard'), 15),
 (('review', 'fire', 'alarm'), 11),
 (('review', 'lighting', 'shop'), 10)]
 

и я хотел бы объединить те элементы, которые похожи, после их определения вместе с их количеством:

 from nltk.stem import PorterStemmer

for elm in trigram_counts:
    ngrams = list(elm[0])
    stemmed_ngrams = []
    for gram in ngrams:
        stemmed_ngrams.append(porter.stem(gram))
        
    print(stemmed_ngrams, elm[1])
    
 

это дает что-то вроде этого :

 ['review', 'shop', 'draw'] 35
['shop', 'draw', 'review'] 32
['field', 'review', 'report'] 24
['review', 'shop', 'draw'] 20
['shop', 'draw', 'return'] 20
['shop', 'draw', 'review'] 18
['site', 'review', 'report'] 17
['respond', 'rfi', 'regard'] 15
['review', 'fire', 'alarm'] 11
['review', 'light', 'shop'] 10
 

Моя цель — объединить, например ['review', 'shop', 'draw'] , и ['shop', 'draw', 'review'] с их соответствующей суммой, которая равна 67

Я думаю, что усложняю это своим решением, перебирая все элементы.

Комментарии:

1. Является trigram_counts ли переменная, которая содержит ваш список кортежей?

2. Каков критерий для подобных? Что кортеж содержит одинаковые (три) строки, а порядок не имеет значения? Что, если кортеж есть ('review', 'shop', 'draw', 'fire') , а другой кортеж есть ('review', 'shop', 'draw') ; они похожи?

3. Я бы использовал словарь с set(inner_tuple) его ключом.

4. Вместо добавления в a list , добавьте в a set . Затем преобразуйте набор в a tuple , используйте в tuple качестве ключа к a dict , значения которого представляют собой текущую сумму, которую вы хотите для этого набора

5. Вы можете отсортировать кортеж, чтобы сравнить их на равенство.

Ответ №1:

Поскольку вы хотите объединить подсчеты из похожих базовых триграмм, вы можете использовать словарь с frozensets в качестве ключей: ключами будут базовые триграммы, а значениями — общее количество.

Вы должны использовать frozensets вместо наборов в качестве ключей, поскольку ключи dict должны быть хешируемыми (что не относится к наборам).

У вас будет что-то вроде этого:

 from collections import defaultdict
from nltk.stem import PorterStemmer

stemmed_trigram_counts = defaultdict(int) # use defaultdict to avoid to have to check if the key exist
porter = PorterStemmer()

for trigram, count in trigram_counts:
   stemmed_trigram = frozenset(porter.stem(word) for word in trigram)
   stemmed_trigram_counts[stemmed_trigram]  = count

print(stemmed_trigram_counts)
 

Это даст вам следующий результат:

 {
   frozenset({'draw', 'review', 'shop'}): 105,
   frozenset({'field', 'report', 'review'}): 24,
   frozenset({'draw', 'return', 'shop'}): 20,
   frozenset({'report', 'review', 'site'}): 17,
   frozenset({'regard', 'respond', 'rfi'}): 15,
   frozenset({'alarm', 'fire', 'review'}): 11,
   frozenset({'light', 'review', 'shop'}): 10
}
 

Примечание: в случае, если порядок имеет значение, вы должны использовать кортежи вместо замороженных наборов