Подсчитайте дубликаты в списке и назначьте сумму в список

#python

#python

Вопрос:

У меня есть список с повторяющимися строками:

 lst = ["abc", "abc", "omg", "what", "abc", "omg"]
  

и я хотел бы создать:

 lst = ["3 abc", "2 omg", "what"]
  

итак, в основном подсчитывайте дубликаты, удаляйте дубликаты и добавляйте сумму в начало строки.

Вот как я это делаю прямо сейчас:

 from collections import Counter
list2=[]
for i in lst:
  y = dict(Counter(i))
  have = list(accumulate(y.items())) # creating [("omg", 3), ...]

  for tpl in have: #
    join_list = []
    if tpl[1] > 1:
      join_list.append(str(tpl[1]) " " tpl[0])
    else:
      join_list.append(tpl[0])
  list2.append(', '.join(join_list))
  

Есть ли более простой способ получить желаемый результат в python?

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

1. Имеет ли значение порядок?

2. Нет, порядок не имеет значения

Ответ №1:

Кажется, вы напрасно усложняете ситуацию. Вот очень питонический подход:

 >>> import collections
>>> class OrderedCounter(collections.Counter, collections.OrderedDict):
...   pass
... 
>>> lst = ["abc", "abc", "omg", "what", "abc", "omg"]
>>> counts = OrderedCounter(lst)
>>> counts
OrderedCounter({'abc': 3, 'omg': 2, 'what': 1})
>>> ["{} {}".format(v,k) if v > 1 else k for k,v in counts.items()]
['3 abc', '2 omg', 'what']
>>> 
  

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

1. Побейте меня, какое более элегантное решение 🙂

2. Как я должен изменить код для создания ['3 abcs', '2 omgs', 'what'] . Итак, в основном добавляя «s» к каждой строке, содержащей число (множественное число)?

3. @Chris измените "{} {}".format(v,k) на "{} {}s".format(v,k)

Ответ №2:

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

 list2 = []
for tpl in have:
    count = "" if tpl[1] == 0 else str(tpl[1]) " "
    list2.append(count   tpl[0])
  

Теперь, чтобы добавить все это в понимание списка:

 list2 = [ ("" if tpl[1] == 0 else str(tpl[1]) " ")   tpl[0] 
          for tpl in have]
  

Ответ №3:

Попробуйте это:

 lst = ["abc", "abc", "omg", "what", "abc", "omg"]
l = [lst.count(i) for i in lst] # Count number of duplicates
d = dict(zip(lst, l)) # Convert to dictionary
lst = [str(d[i]) ' ' i if d[i]>1 else i for i  in d] # Convert to list of strings
  

Ответ №4:

Другое возможное решение с комментариями, чтобы помочь…

 import operator

#list
lst = ["abc", "abc", "omg", "what", "abc", "omg"]

#dictionary
countDic = {}

#iterate lst to populate dictionary: {'what': 1, 'abc': 3, 'omg': 2}
for i in lst:
    if i in countDic:
        countDic[i]  = 1
    else:
        countDic[i] = 1

#clean list
lst = []

#convert dictionary to an inverse list sorted by value: [('abc', 3), ('omg', 2), ('what', 1)]
sortedLst = sorted(countDic.items(), key=operator.itemgetter(0))

#iterate sorted list to populate list
for k in sortedLst:
    if k[1] != 1:
        lst.append(str(k[1])   " "   k[0])
    else:
        lst.append(k[0])

#result
print lst
  

Вывод:

 ['3 abc', '2 omg', 'what']
  

Ответ №5:

Это единственный Pythonic способ сделать это, и он также быстрый.

 import collections

lst = ["abc", "abc", "omg", "what", "abc", "omg"]
duplicates = collections.Counter(lst)

lst = [f"{value} {key}"
       if value > 1 else key
       for (key, value) in duplicates.items()]
  

Примечание: этот код работает только с Python 3.6 из-за синтаксиса f-string в понимании списка.