2016-07-02 4 views
5

Я хочу найти начальное положение самой длинной последовательности 1 в моем массиве:найти начальное положение самой длинной последовательности 1-х

a1=[0,0,1,1,1,1,0,0,1,1] 
#2 

Я после этой answer, чтобы найти длину самой длинной последовательности , Однако я не смог определить позицию.

ответ

3

Вдохновленный this solution, вот векторизованный подход к решению его -

# Get start, stop index pairs for islands/seq. of 1s 
idx_pairs = np.where(np.diff(np.hstack(([False],a1==1,[False]))))[0].reshape(-1,2) 

# Get the island lengths, whose argmax would give us the ID of longest island. 
# Start index of that island would be the desired output 
start_longest_seq = idx_pairs[np.diff(idx_pairs,axis=1).argmax(),0] 

Пример запуска -

In [89]: a1 # Input array 
Out[89]: array([0, 0, 1, 1, 1, 1, 0, 0, 1, 1]) 

In [90]: idx_pairs # Start, stop+1 index pairs 
Out[90]: 
array([[ 2, 6], 
     [ 8, 10]]) 

In [91]: np.diff(idx_pairs,axis=1) # Island lengths 
Out[91]: 
array([[4], 
     [2]]) 

In [92]: np.diff(idx_pairs,axis=1).argmax() # Longest island ID 
Out[92]: 0 

In [93]: idx_pairs[np.diff(idx_pairs,axis=1).argmax(),0] # Longest island start 
Out[93]: 2 
1

Вы можете использовать цикл и проверьте следующие несколько пунктов (длины m где m длина макс) такие же, как максимальная длина:

# Using your list and the answer from the post you referred 
from itertools import groupby 
L = [0,0,1,1,1,1,0,0,1,1] 
m = max(sum(1 for i in g) for k, g in groupby(L)) 
# Here is the for loop 
for i, s in enumerate(L): 
    if len(L) - i + 2 < len(L) - m: 
     break 
    if s == 1 and 0 not in L[i:i+m]: 
     print i 
     break 

Это даст:

2 
2

Это похоже на работу, используя groupby из itertools, это идет только по списку раз:

from itertools import groupby 

pos, max_len, cum_pos = 0, 0, 0 

for k, g in groupby(a1): 
    if k == 1: 
     pat_size = len(list(g)) 
     pos, max_len = (pos, max_len) if pat_size < max_len else (cum_pos, pat_size) 
     cum_pos += pat_size 
    else: 
     cum_pos += len(list(g)) 

pos 
# 2 
max_len 
# 4 
1

Другой способ сделать в одном цикле, но не прибегая к itertoolgroupby.

max_start = 0 
max_reps = 0 
start = 0 
reps = 0 
for (pos, val) in enumerate(a1): 
    start = pos if reps == 0 else start 
    reps = reps + 1 if val == 1 else 0 
    max_reps = max(reps, max_reps) 
    max_start = start if reps == max_reps else max_start 

Это также может быть сделано в один вкладыш моды с использованием reduce:

max_start = reduce(lambda (max_start, max_reps, start, reps), (pos, val): (start if reps == max(reps, max_reps) else max_start, max(reps, max_reps), pos if reps == 0 else start, reps + 1 if val == 1 else 0), enumerate(a1), (0, 0, 0, 0))[0] 

В Python 3, вы не можете распаковать кортежи внутри определения lambda аргументы, так что предпочтительнее, чтобы определить функцию, используя def первый:

def func(acc, x): 
    max_start, max_reps, start, reps = acc 
    pos, val = x 
    return (start if reps == max(reps, max_reps) else max_start, 
      max(reps, max_reps), 
      pos if reps == 0 else start, 
      reps + 1 if val == 1 else 0) 

max_start = reduce(func, enumerate(a1), (0, 0, 0, 0))[0] 

В любом из этих трех случаев, max_start дает ответ (т.е. 2).

2

Более компактный однострочный с использованием groupby(). Использует enumerate() на необработанных данных, чтобы сохранить начальные позиции через конвейер анализа, равномерно заканчивая списком кортежей [(2, 4), (8, 2)], каждый кортеж, содержащий начальную позицию и длину ненулевых прогонов :

from itertools import groupby 

L = [0,0,1,1,1,1,0,0,1,1] 

print max(((lambda y: (y[0][0], len(y)))(list(g)) for k, g in groupby(enumerate(L), lambda x: x[1]) if k), key=lambda z: z[1])[0] 

lambda: x является функциональной клавишей для groupby(), так как мы перечислили L

lambda: y пакетов до результатов нам нужно, так как мы можем только оценить g один раз, без сохранения

lambda: z является ключевой функцией для max() для вытягивания длин

Печатает '2', как ожидалось.

0

Использование more_itertools, библиотека третья сторона:

Учитывая

import itertools as it 

import more_itertools as mit 


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

Код

longest_contiguous = max([tuple(g) for _, g in it.groupby(lst)], key=len) 
longest_contiguous  
# (1, 1, 1, 1) 

pred = lambda w: w == longest_contiguous 
next(mit.locate(mit.windowed(lst, len(longest_contiguous)), pred=pred)) 
# 2 

Смотри также more_itertools.locate строку документации для получения подробной информации о том, как эти инструменты работают.

Смежные вопросы