Python — поиск каждого вхождения значения в смешанном массиве (целые числа, списки)

#python #arrays #for-loop

#python #массивы #для цикла

Вопрос:

У меня есть массив: x = [ [1, 2], 1, 1, [2, 1, [1, 2]] ] в котором я хочу подсчитать каждое вхождение числа 1 и сохранить это число в переменной one_counter . x.count(1) возвращает только 2 вхождения 1 , что недостаточно.

Приведенный ниже код служит моей цели и сохраняется 5 в one_counter , однако он выглядит беспорядочно и кажется мне непитоническим.

Есть предложения, как я могу улучшить его pythonicity и расширить его до более размерных списков?

Спасибо!

 x = [[1, 2], 1, 1, [2, 1, [1, 2]]]

one_counter = 0

for i in x:
    if type(i) == list:
        for j in i:
            if type(j) == list:
                for k in j:
                    if k == 1:
                        one_counter  = 1

            else:
                if j == 1:
                    one_counter  = 1

    else:
        if i == 1:
            one_counter  = 1
  

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

1. Какое отношение к этому имеет масштабирование?

2. @IgnacioVazquez-Abrams Я предполагаю, что он злоупотребил словом Scale, возможно, он имел в виду расширение своего типа данных в более размерные списки.

3. @DhruvPathak Да, сэр! Я неправильно понял это для масштаба.

4. Итак, как вы в конечном итоге получили этот список и зачем вам нужно это количество? Все это кажется странно искусственным.

5. @Karl Ты бы расстроился, если бы я сказал, что это я практиковался, наткнулся на дорожный блок и попросил о помощи?

Ответ №1:

Вы могли бы использовать рекурсию:

 def flatten_count(iterable, element):
    count = 0
    for item in iterable:
        if item == element:
            count  = 1
        if isinstance(item, list):
            count  = flatten_count(item, element)
    return count
  

Или более кратко:

 def flatten_count(iterable, element):
    return sum(
        flatten_count(item, element) if isinstance(item, list) else item == element
        for item in iterable 
    )
  

Используйте так:

 >>> x = [[1, 2], 1, 1, [2, 1, [1, 2]]]
>>> print(flatten_count(x, 1))
5
  

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

1. Большое спасибо, Марк! Это имеет смысл, и теперь я лучше понимаю рекурсию вместе с удобством, которым является isinstance().

Ответ №2:

Хакерское решение, работающее путем преобразования типа данных в строку:http://codepad.org/vNEv6B8M

 import re
x = [ [1, 2], 1, 1, [2, 1, [1, 2]] ]
nums = [int(i) for i in re.findall(r'd ', str(x))]
print(nums.count(1))
  

Ответ №3:

Я думаю, что лучше разделить эту задачу на 2 части.

Часть 1

Часть 1 заключается в создании генератора, который сгладит входной список.

 def flatten_list(L):
    for i in L:
        if isinstance(i,list):
            for j in flatten_list(i):
                yield j
        else:
            yield i
  

Тестирование выходных данных:

 x = [[1, 2], 1, 1, [2, 1, [1, 2]]]

for i in flatten_list(x):
    print i
  

Вывод:

 1
2
1
1
2
1
1
2
  

Часть 2

Часть 2 заключается в использовании сжатого списка для подсчета количества вхождений 1 в нем:

 print(sum(i==1 for i in flatten_list(x))) 
  

Вывод:

 5
  

Обратите внимание, что i==1 возвращает True , если i=1 и False если i не равно 1 . Но True равно 1 и False равно 0 , поэтому sum просто вычисляет количество True вхождений (которое в данном случае равно 5 ).

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

1. Спасибо, что разбили его. Я действительно ценю это.