как я могу создать вывод количества слов в python, просто используя функцию сокращения?

У меня есть следующий список кортежей: [('a', 1), ('a', 1), ('b', 1), ('c',1), ('a', 1), ('c', 1)]

Я хотел бы знать, могу ли я использовать функцию reduce Python для их объединения и получения следующего вывода: [('a', 3), ('b', 1), ('c', 2)]

Или, если есть другие способы, я тоже хотел бы знать (цикл в порядке)


person CHL    schedule 02.04.2017    source источник
comment
Если вы не делаете это одновременно, лучший способ — использовать HashMap с ‹tuple[0], частотой?   -  person Jeremy Fisher    schedule 02.04.2017
comment
Возможный дубликат Как суммировать значения кортежи с одинаковыми именами в Python   -  person manvi77    schedule 02.04.2017


Ответы (3)


Это кажется трудным для достижения с помощью reduce, потому что если оба кортежа, которые вы «сокращаете», не имеют одной и той же буквы, вы не можете вычислить результат. Как уменьшить ('a',1) и ('b',1) до какого-то жизнеспособного результата?

Лучшее, что я мог сделать, это l = functools.reduce(lambda x,y : (x[0],x[1]+y[1]) if x[0]==y[0] else x+y,sorted(l))

меня это достало ('a', 3, 'b', 1, 'c', 1, 'c', 1). Таким образом, для первого элемента это сработало, но для остальных потребовалось бы больше одного прохода (воссоздание кортежей и создание другого аналогичного reduce, мягко говоря, не очень эффективно!).

Во всяком случае, вот 2 рабочих способа сделать это

Во-первых, используя collections.Counter подсчет элементов одного типа:

l = [('a', 1), ('a', 1), ('b', 1), ('c',1), ('a', 1), ('c', 1)]

import collections

c = collections.Counter()
for a,i in l:
    c[a] += i

Мы не можем использовать listcomp, потому что каждый элемент имеет вес (даже если здесь он равен 1).

Результат: словарь: Counter({'a': 3, 'c': 2, 'b': 1})

Второй вариант: используйте itertools.groupby в отсортированном списке, группируя по имени/букве и выполняя сумму целых чисел, имеющих одну и ту же букву:

print ([(k,sum(e for _,e in v)) for k,v in itertools.groupby(sorted(l),key=lambda x : x[0])])

результат:

[('a', 3), ('b', 1), ('c', 2)]
person Jean-François Fabre    schedule 02.04.2017

Альтернативный подход с использованием подкласса defaultdict и sum:

import collections

l = [('a', 1), ('a', 1), ('b', 1), ('c',1), ('a', 1), ('c', 1)]
d = collections.defaultdict(list)
for t in l:
    d[t[0]].append(t[1])

result = [(k,sum(v)) for k,v in d.items()]
print(result)

Выход:

[('b', 1), ('a', 3), ('c', 2)]
person RomanPerekhrest    schedule 02.04.2017

Другой способ заключается в создании собственной функции сокращения.
Например:
l = [('a', 1), ('a', 1), ('b', 1), ('c ',1), ('а', 1), ('с', 1)]

def myreduce(func , seq):
    output_dict = {}
    for k,v in seq:
        output_dict[k] = func(output_dict.get(k,0),v)
    return output_dict  

myreduce((лямбда-сумма,значение:общая+сумма),l)

вывод:
{'а': 3, 'б': 1, 'в': 2}

позже вы можете изменить сгенерированный вывод в виде списка кортежей.

person JArpit    schedule 08.05.2019