Как эффективно рассчитать непоследовательное количество вхождений элемента в списке? - PullRequest
2 голосов
/ 03 марта 2020

Итак, я пытаюсь выяснить, сколько раз определенный элемент не появляется последовательно в списке. Под этим я подразумеваю:

list = [10,10,10,11,12,10,12,14,10,10,10]
element_searched = 10

=> expected_output = 3

Так что это означает, что 10 появляется в списке 3 раза.

Мой код, который, кажется, работает:

elements = [11, 10, 12]
row = [10,10,10,10,10,10,10,10,10,11,11,11,11,11,10,10,10,10,12,12,12,12,12,11,11,11,11,12,12,12,12,10]

element_on = False
for element in elements:
    sequence = 0
    for i in range(len(row)):
        if element == row[i] and element_on==False:
            sequence += 1
            element_on = True
        elif element==row[i] and element_on==True:
            pass
        elif element != row[i] and element_on==True:
            element_on = False
        #
        elif element != row[i] and element_on == False:
            element_on = False
        #
    print(f"For element {element} the number ob sequences is: {sequence} ")

Я получаю желаемый результат, но мне интересно, есть ли более элегантный и особенно более быстрый способ.

Ответы [ 4 ]

2 голосов
/ 03 марта 2020

Попробуйте:

row = [10,10,10,10,10,10,10,10,10,11,11,11,11,11,10,10,10,10,12,12,12,12,12,11,11,11,11,12,12,12,12,10]
sr = pd.Series(row, name = "x")
sr[sr.groupby(sr.shift(-1).bfill(0).ne(sr)).transform('cumcount')==1].value_counts()

Вывод:

10    3
12    2
11    2

Первый столбец - значение x, второй - количество последовательностей.

Более компактный и быстрый путь:

from  itertools import groupby    
pd.Series([k for k, g in groupby(row)]).value_counts()

Другое решение:

np.unique([k for k, g in groupby(row)], return_counts=True)

Результат:

(array([10, 11, 12]), array([3, 2, 2], dtype=int64))

Альтернативно использовать np.bincount:

np.bincount([k for k, g in groupby(row)])

Но вывод будет немного другим:

array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 2, 2], dtype=int64)
1 голос
/ 03 марта 2020

Я бы использовал простой словарь:

row = [10,10,10,10,10,10,10,10,10,11,11,11,11,11,10,10,10,10,12,12,12,12,12,11,11,11,11,12,12,12,12,10]

counter = {}
last_item = None
for item in row:
    if last_item != item:
        counter[item] = counter.get(item, 0) + 1
        last_item = item

print (counter)
1 голос
/ 03 марта 2020

Несколько мыслей, которые должны вас направить:

  • вам нужна переменная, в которой будет храниться предыдущее значение
  • карта элементов, ключом является значение элемента, значение, являющееся числом найденных к настоящему времени вхождений
  • на каждой итерации, проверяет, равен ли текущий элемент предыдущему элементу, и если нет, то увеличивает значение элемента карты, имеющего текущий элемент, в качестве установленного ключа
  • до текущего значения на каждом шаге
1 голос
/ 03 марта 2020

Я думаю, это то, что вы хотите. Сгруппируйте список по схожим элементам, а затем сложите суммы

import itertools

element_searched = 10

expected_output = sum([i.count(element_searched) for i in itertools.groupby(list)])

3

...