2017-04-26 1 views
2

[1,2,3,4,5,6,7,8,9,10] gegeben, ein Schiebefenster von 3 Artikeln zu einer Zeit zu erhalten,:Skipping das Schiebefensters

[(1, 2, 3), (2, 3, 4), (3, 4, 5), (4, 5, 6), (5, 6, 7), (6, 7, 8), (7, 8, 9), (8, 9, 10)] 

Von https://stackoverflow.com/q/42220614/610569, ein Schiebefenster einer Sequenz kann erreicht werden durch:

def per_window(sequence, n=1): 
    """ 
    Returns a sliding window. 
    From https://stackoverflow.com/q/42220614/610569 
     >>> list(per_window([1,2,3,4], n=2)) 
     [(1, 2), (2, 3), (3, 4)] 
     >>> list(per_window([1,2,3,4], n=3)) 
     [(1, 2, 3), (2, 3, 4)] 
    """ 
    start, stop = 0, n 
    seq = list(sequence) 
    while stop <= len(seq): 
     yield tuple(seq[start:stop]) 
     start += 1 
     stop += 1 

Aber wenn es einige Einschränkungen gibt, die ich in das gleitende Fenster einfügen möchte, und ich möchte nur die Fenster erhalten, wo ein bestimmtes Element existiert.

Lasst uns sagen, dass ich nur die Fenster möchten, die 4 enthält, konnte ich so etwas wie:

>>> [window for window in per_window(x, 3) if 4 in window] 
[((2, 3, 4), (3, 4, 5), (4,5,6)] 

Aber irgendwie die Schleife hat immer noch durch die ganze Liste von Fenstern zu verarbeiten und überprüfen, durch die, wenn die Bedingungen.

Ich könnte einige überspringen, indem Sie nach den Positionen von 4 suchen und die Eingabe auf die per_window, z.

# Input sequence. 
x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 
# Window size. 
n = 3 
# Constraint. 
c = 4 
# Set the index to 0 
i = 0 
while i < len(x)-n: 
    i = x.index(4, i) 
    # First window where the constraint is met. 
    left = i - (n-1) 
    if left > 0: 
     print (list(per_window(x[left:i], 3))) 
    right = i + n 
    if right < len(x): 
     print (list(per_window(x[i:right], 3))) 
    i = right 

(Beachten Sie den Code oben mit der ifs funktionieren nicht =()

Statt den Index außerhalb der per_window Funktion zu finden, ist es eine andere Möglichkeit, eine solche Einschränkung in der per_window Funktion hinzufügen ?


EDITED

Nach der Lektüre @ RaymondHettinger Antwort:

def skipping_window(sequence, target, n=3): 
    """ 
    Return a sliding window with a constraint to check that 
    target is inside the window. 
    From https://stackoverflow.com/q/43626525/610569 
    """ 
    start, stop = 0, n 
    seq = list(sequence) 
    while stop <= len(seq): 
     subseq = seq[start:stop] 
     if target in subseq: 
      yield tuple(seq[start:stop]) 
     start += 1 
     stop += 1 
     # Fast forwarding the start. 
     # Find the next window which contains the target. 
     try: 
      # `seq.index(target, start) - (n-1)` would be the next 
      # window where the constraint is met. 
      start = max(seq.index(target, start) - (n-1), start) 
      stop = start + n 
     except ValueError: 
      break 

[out]:

>>> x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 
>>> list(skipping_window(x, 4, 3)) 
[(2, 3, 4), (3, 4, 5), (4, 5, 6)] 

Antwort

3

Statt den Index außerhalb der per_window Funktion zu finden, ist es eine andere Möglichkeit, eine solche Einschränkung in der per_window Funktion hinzufügen?

Ja, können Sie den Zustand kurz vor der Ausbeute hinzufügen:

def per_window(sequence, target, n=1): 
    start, stop = 0, n 
    seq = list(sequence) 
    while stop <= len(seq): 
     subseq = seq[start:stop] 
     if target in subseq: 
      yield tuple(subseq) 
     start += 1 
     stop += 1 
+0

Aber das würde jedes mögliche Fenster noch eine Schleife durch, nur, dass es nicht nachgibt, wenn es die Einschränkung nicht, nicht wahr? = ( – alvas

+1

Die angegebene Antwort entspricht der gestellten Frage. Außerdem war klar, dass Sie bereits den Pfad zur weiteren Optimierung durch Verwendung von * index() * kennen, um schnell zur nächsten möglichen passenden Teilfolge zu gelangen. –

+1

Danke @RaymondHettinger! bestätige, dass die "Schnellvorlauf" -Optimierung nicht enthalten ist. Ich habe überlegt, ob ich etwas verpasst habe =) – alvas

Verwandte Themen