Поиск последовательных дубликатов и перечисление их индексов того, где они встречаются в Python - PullRequest
0 голосов
/ 08 февраля 2019

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

mylist = [1,1,1,1,1,1,1,1,1,1,1,
        0,0,1,1,1,1,0,0,0,0,0,
        1,1,1,1,1,1,1,1,0,0,0,0,0,0]

Моя цель - найти, где в строке пять или более нулей, а затем перечислить индексы того, где это происходит, например, выводпоскольку это будет:

[17,21][30,35]

вот что я пробовал / видел в других вопросах, задаваемых здесь:

def zero_runs(a):
    # Create an array that is 1 where a is 0, and pad each end with an extra 0.
    iszero = np.concatenate(([0], np.equal(a, 0).view(np.int8), [0]))
    absdiff = np.abs(np.diff(iszero))
    # Runs start and end where absdiff is 1.
    ranges = np.where(absdiff == 1)[0].reshape(-1, 2)
    return ranges

    runs = zero_runs(list)

это дает вывод:

[0,10]
[11,12]
...

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

Ответы [ 4 ]

0 голосов
/ 08 февраля 2019

Ваша текущая попытка очень близка.Он возвращает все серии последовательных нулей в массиве, поэтому все, что вам нужно сделать, это добавить проверку, чтобы отфильтровать серии из менее чем 5 последовательных нулей.


def threshold_zero_runs(a, threshold):
    iszero = np.concatenate(([0], np.equal(a, 0).view(np.int8), [0]))
    absdiff = np.abs(np.diff(iszero))
    ranges = np.where(absdiff == 1)[0].reshape(-1, 2)

    m = (np.diff(ranges, 1) >= threshold).ravel()
    return ranges[m] 

array([[17, 22],
       [30, 36]], dtype=int64)
0 голосов
/ 08 февраля 2019

Используйте оператор shift в массиве.Сравните смещенную версию с оригинальной.Где они не совпадают, у вас есть переход.Затем вам нужно только идентифицировать смежные переходы, которые находятся на расстоянии не менее 5 позиций.

Можете ли вы взять его оттуда?

0 голосов
/ 08 февраля 2019

Другой способ использования itertools.groupby и enumerate.

Сначала найдите нули и индексы:

from operator import itemgetter
from itertools import groupby

zerosList = [
    list(map(itemgetter(0), g)) 
    for i, g in groupby(enumerate(mylist), key=itemgetter(1)) 
    if not i
]
print(zerosList)
#[[11, 12], [17, 18, 19, 20, 21], [30, 31, 32, 33, 34, 35]]

Теперь просто отфильтруйте zerosList:

runs = [[x[0], x[-1]] for x in zerosList if len(x) >= 5]
print(runs)
#[[17, 21], [30, 35]]
0 голосов
/ 08 февраля 2019

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

from itertools import groupby

lst = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0]

groups = [(k, sum(1 for _ in g)) for k, g in groupby(lst)]

cursor = 0
result = []
for k, l in groups:
    if not k and l >= 5:
        result.append([cursor, cursor + l - 1])
    cursor += l

print(result)

Выход

[[17, 21], [30, 35]]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...