2016-07-02 6 views

Antwort

3

Inspiriert von this solution, hier ist ein vektorisiert Ansatz, es zu lösen -

# 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] 

Probendurchlauf - mit groupby von itertools

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

Sie könnten eine for-Schleife verwenden und überprüfen, ob die nächsten Artikel (der Länge m wo m ist die maximale Länge) die gleiche wie die maximale Länge sind:

# 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 

Dies gibt:

2 
2

Dies scheint zu funktionieren, das geht nur durch die Liste einmal:

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

Eine andere Möglichkeit, in einer einzigen Schleife zu tun, aber ohne auf itertool 's groupby.

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 

Dies könnte auch in einer Art und Weise mit reduce Einzeiler erfolgen:

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] 

In Python 3 nicht Tupeln in der lambda Argumente Definition entpacken kann, so ist es vorzuziehen, um die Funktion zu definieren, unter Verwendung von def zuerst:

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] 

In jedem der drei Fälle, max_start gibt Ihre Antwort (dh 2).

2

Ein kompakter Einleiner mit groupby(). Verwendet enumerate() für die Rohdaten, um die Startpositionen durch die Analysepipeline zu halten, und endet schließlich mit der Liste der Tupel [(2, 4), (8, 2)] jedes Tupel, das die Startposition und die Länge von Nicht-Null-Läufen enthält :

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 ist die Schlüsselfunktion für groupby() da wir L

lambda: y Pakete bis Ergebnisse, die wir aufgezählt müssen, da wir nur g einmal auswerten kann, ohne

lambda: z Speichern der Schlüsselfunktion füristzum Herausziehen der Längen

Druckt '2' wie erwartet.

0

more_itertools Verwendung, eine Drittanbieter-Bibliothek:

Gegeben

import itertools as it 

import more_itertools as mit 


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

-Code

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 

Siehe auch die more_itertools.locate docstring für Details, wie diese Werkzeuge arbeiten.