Как мне рассчитать количество идентичных элементов в списке?

#python #python-3.x

#python #python-3.x

Вопрос:

У меня есть (очень длинный) список с такой структурой:

 li1 = [[1.4, b][1.5, a][1.6, c][1,4, b][1.7,c][1.4, a][1.6,c]]
  

Я хочу написать цикл, который вычисляет количество элементов li1[i][0 ]` с одинаковым значением и помещает эту информацию в новый список, вот так:

 li2 = [[1.4, 3][1.5, 1][1.6, 2][1.7, 1]]
  

Проблема для меня в том, что я не знаю, какое значение или сколько разных значений я ищу..

Спасибо

Ответ №1:

 from collections import Counter
a, b, c = 'abc'
li1 = [[1.4, b], [1.5, a], [1.6, c], [1.4, b], [1.7, c], [1.4, a], [1.6, c]]
sorted(Counter(x[0] for x in li1).items())
  

( map list воспользуйтесь этим, если вам отчаянно нужен список списков.)

Ответ №2:

 >>> li1 = [[1.4, 'b'],[1.5, 'a'],[1.6, 'c'],[1.4, 'b'],[1.7,'c'],[1.4, 'a'],[1.6,'c']]
  

Сначала мы создаем словарь с ключами типа (1.4,'b') и значениями, обозначающими количество этих ключевых элементов в исходном списке:

 >>> d = {}
>>> for el in li1:
    el = el[0]
    d[el] = d.get(el,0)   1
  

Итак, словарь выглядит следующим образом:

 >>> d
{1.5: 1, 1.4: 3, 1.7: 1, 1.6: 2}
  

Также обратите внимание, что используется d.get . Поскольку изначально словарь не содержит элементов, поэтому get возвращает, 0 когда элемента нет (второй аргумент get ). Существуют другие методы для достижения такого поведения: вы можете использовать DefalutDict или Counter , как используется в другом ответе.

Затем мы используем словарь для создания необходимого списка:

 >>>[[key,value] for key,value in d.items()]
[[1.5, 1], [1.4, 3], [1.7, 1], [1.6, 2]]
  

Ответ №3:

Поскольку вас интересует только первое значение списка, первым шагом является извлечение его из каждого из подсписков (которые, кстати, должны быть тупелями).

 >>> a,b,c = 'abc'
>>> li1 = [[1.4, b], [1.5, a], [1.6, c], [1,4, b], [1.7, c], [1.4, a], [1.6, c]]
>>> firsts = map(lambda sublist: sublist[0], li1)
  

map вызывает его первый аргумент с элементом второго аргумента. Поскольку первым аргументом здесь является анонимная функция (lambda), которая возвращает первый элемент своего аргумента, значение firsts теперь является списком этих первых элементов:

 >>> firsts
[1.4, 1.5, 1.6, 1, 1.7, 1.4, 1.6]
  

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

 >>> firsts = [sublist[0] for sublist in li1]
>>> firsts
[1.4, 1.5, 1.6, 1, 1.7, 1.4, 1.6]
  

Результатом сопоставления (в Python 2) и понимания списка является список, который сохраняется в памяти. Это не проблема для нашего небольшого списка li1 , но может стать проблемой для больших списков ввода. Поскольку мы хотим подсчитать значения только один раз, нам на самом деле не нужно их сохранять, и поэтому мы можем использовать выражение генератора (которое «вычисляет» каждое значение во времени):

 >>> first = (sublist[0] for sublist in li1)
  

firsts теперь это объект-генератор, из которого мы можем получить первые значения.

Теперь перейдем к подсчету. К счастью, Python 2.6 предоставляет Counter класс, который мы можем использовать:

 >>> import collections
>>> counter = collections.Counter(firsts)
>>> counter.most_common()
[(1.4, 2), (1.6, 2), (1.5, 1), (1.7, 1), (1, 1)]
  

Обратите внимание, что результат выражается в tupels, что, вероятно, в любом случае является тем, что вы хотите. Если вам действительно нужен список (например, потому что вы хотите что-то добавить к элементам), используйте map для составления списка из каждого кортежа:

 >>> map(list, counter.most_common())
[[1.4, 2], [1.6, 2], [1.5, 1], [1.7, 1], [1, 1]]
  

В общем, короткий способ записать все это:

 import collections
a,b,c = 'abc'
li1 = [[1.4, b], [1.5, a], [1.6, c], [1,4, b], [1.7, c], [1.4, a], [1.6, c]]
li2 = collections.Counter(sublist[0] for sublist in li1).most_common()
  

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

1. Это просто с TypeError: unhashable type: 'list' и близко не подходит к тому, что запрашивает OP (подсчет дубликатов).

2. -1 Прочитайте еще раз, внимательно. Это все еще не выполняет то, что запрашивает OP. Он просто удаляет полностью повторяющиеся кортежи, вместо подсчета дублирующихся первых элементов.

3. @delnan обновлен решением, которое действительно учитывается, включая некоторое объяснение того, как и почему это работает, и использование most_common вместо items для получения результата, отсортированного по встречаемости.