Я хочу узнать, сколько раз x появляется во вложенном списке.
если список:
list = [1, 2, 1, 1, 4]
list.count(1)
>>3
Хорошо. Но если список такой:
list = [[1, 2, 3],[1, 1, 1]]
Как я могу узнать, сколько раз появляется 1? В этом случае 4.
Я хочу узнать, сколько раз x появляется во вложенном списке.
если список:
list = [1, 2, 1, 1, 4]
list.count(1)
>>3
Хорошо. Но если список такой:
list = [[1, 2, 3],[1, 1, 1]]
Как я могу узнать, сколько раз появляется 1? В этом случае 4.
Вот еще один подход к сглаживанию вложенной последовательности. После того, как последовательность выровнена, можно легко проверить количество элементов.
def flatten(seq, container=None):
if container is None:
container = []
for s in seq:
try:
iter(s) # check if it's iterable
except TypeError:
container.append(s)
else:
flatten(s, container)
return container
c = flatten([(1,2),(3,4),(5,[6,7,['a','b']]),['c','d',('e',['f','g','h'])]])
print(c)
print(c.count('g'))
d = flatten([[[1,(1,),((1,(1,))), [1,[1,[1,[1]]]], 1, [1, [1, (1,)]]]]])
print(d)
print(d.count(1))
Приведенный выше код печатает:
[1, 2, 3, 4, 5, 6, 7, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
1
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
12
Модули itertools
и collections
получили именно то, что вам нужно (сгладьте вложенные списки с помощью itertools.chain
и считайте с помощью collections.Counter
import itertools, collections
data = [[1,2,3],[1,1,1]]
counter = collections.Counter(itertools.chain(*data))
print counter[1]
Используйте рекурсивную функцию сглаживания вместо itertools.chain
для сглаживания вложенных списков произвольной глубины уровня
import operator, collections
def flatten(lst):
return reduce(operator.iadd, (flatten(i) if isinstance(i, collections.Sequence) else [i] for i in lst))
reduce
с operator.iadd
использовался вместо sum
, так что развертка создается только один раз и обновляется на месте
Попробуй это:
reduce(lambda x,y: x+y,list,[]).count(1)
Обычно вы начинаете с пустого списка []
и добавляете к нему каждый элемент списка list
. В этом случае элементы сами по себе являются списками, и вы получаете сплющенный список.
PS: Только что проголосовали за аналогичный ответ в другом вопросе!
PPS: Только что проголосовали за это решение!
Если есть только один уровень вложенности, выравнивание может быть выполнено с помощью этого расширения списка:
>>> L = [[1,2,3],[1,1,1]]
>>> [ item for sublist in L for item in sublist ].count(1)
4
>>>
На всякий случай: подсчитайте до любой произвольной глубины вложенности, обрабатывая кортежи, списки и аргументы:
hits = lambda num, *n: ((1 if e == num else 0)
for a in n
for e in (hits(num, *a) if isinstance(a, (tuple, list)) else (a,)))
lst = [[[1,(1,),((1,(1,))), [1,[1,[1,[1]]]], 1, [1, [1, (1,)]]]]]
print sum(hits(1, lst, 1, 1, 1))
15
lambda
обидчика здесь ;-). Это также отвечает на вопрос, как рекурсивно встроить генератор в себя :-). 29.04.2011 def nested_count(lst, x):
return lst.count(x) + sum(
nested_count(l,x) for l in lst if isinstance(l,list))
Эта функция возвращает количество вхождений, плюс рекурсивный вложенный счетчик во всех содержащихся подсписках.
>>> data = [[1,2,3],[1,1,[1,1]]]
>>> print nested_count(data, 1)
5
Следующая функция сглаживает списки списков любой глубины (a), добавляя не-списки в результирующий выходной список и рекурсивно обрабатывая списки:
def flatten(listOrItem, result = None):
if result is None: result = [] # Ensure initial result empty.
if type(listOrItem) != type([]): # Handle non-list by appending.
result.append(listOrItem)
else:
for item in listOrItem: # Recursively handle each item in a list.
flatten(item, result)
return result # Return flattened container.
mylist = flatten([[1,2],[3,'a'],[5,[6,7,[8,9]]],[10,'a',[11,[12,13,14]]]])
print(f'Flat list is {mylist}, count of "a" is {mylist.count("a")}')
print(flatten(7))
Если у вас есть сплющенный список, можно просто использовать в нем count
. Результат этого кода:
Flat list is [1, 2, 3, 'a', 5, 6, 7, 8, 9, 10, 'a', 11, 12, 13, 14], count of "a" is 2
[7]
Обратите внимание на поведение, если вы не передаете фактический список, предполагается, что вам нужен список, в любом случае, содержащий только один элемент.
Если вы не хотите создавать сплющенный список, вы можете просто использовать аналогичный метод для получения количества любого элемента в списке списков, например:
def deepCount(listOrItem, searchFor):
if type(listOrItem) != type([]): # Non-list, one only if equal.
return 1 if listOrItem == searchFor else 0
subCount = 0 # List, recursively collect each count.
for item in listOrItem:
subCount += deepCount(item, searchFor)
return subCount
deepList = [[1,2],[3,'a'],[5,[6,7,[8,9]]],[10,'a',[11,[12,13,14]]]]
print(f'Count of "a" is {deepCount(deepList, "a")}')
print(f'Count of 13 is {deepCount(deepList, 13)}')
print(f'Count of 99 is {deepCount(deepList, 99)}')
Как и ожидалось, результат такой:
Count of "a" is 2
Count of 13 is 1
Count of 99 is 0
(a) Конечно, вплоть до ограничений, налагаемых самим Python, ограничения, которые вы можете увеличить, просто добавив это в начало вашего кода:
import sys
sys.setrecursionlimit(1001) # I believe default is 1000.
Я упоминаю, что только в случае у вас есть несколько очень глубоко вложенных структур, но вам это действительно не нужно. Если вы так глубоко вложены, то, вероятно, делаете что-то не так :-)
'a'
на самом деле является итерируемой. Это означает, что он будет продолжать вызывать рекурсию. 16.10.2020iter
изменилось между версиями или опубликованный мной код был неправильным с того дня Я написал, и ошибка осталась незамеченной. 17.10.2020