2015-12-02 3 views
1

J'ai utilisé le fameux code folowing pour mon windoe glisser dans le document texte tokenized:Fenêtre coulissante en Python

def window(fseq, window_size): 
    "Sliding window" 
    it = iter(fseq) 
    result = tuple(islice(it, 0, window_size, round(window_size/4))) 
    if len(result) == window_size: 
     yield result 
    for elem in it: 
     result = result[1:] + (elem,) 
     result_list = list(result) 
     yield result_list 

quand je veux appeler ma fonction avec la taille de la fenêtre inférieure à 6, tout est ok, mais quand je l'augmente, le début du texte est coupé. Par exemple:

c=['A','B','C','D','E', 'F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'] 
print(list(window(c, 4))) 
print(list(window(c, 8))) 

Sortie:

[('A', 'B', 'C', 'D'), ['B', 'C', 'D', 'E'], ['C', 'D', 'E', 'F'], ['D', 'E', 'F', 'G'], ['E', 'F', 'G', 'H'], ['F', 'G', 'H', 'I'],... 

[['C', 'E', 'G', 'I'], ['E', 'G', 'I', 'J'], ['G', 'I', 'J', 'K'], ['I', 'J', 'K', 'L'], ['J', 'K', 'L', 'M']... 

Qu'est-ce qui ne va pas? Et pourquoi dans la première sortie le premier élément est entre parenthèses?

Ma sortie prévue pour print(list(window(c, 8))) est:

[['A','B','C', 'D', 'E', 'F','G','H'], ['C', 'D', 'E', 'F', 'G', 'H', 'I', 'J'], ['E', 'F', 'G', 'H', 'I', 'K', 'L', 'M']... 
+0

Où avez-vous obtenu ce code de? Il diffère matériellement des solutions sur [Roller ou glisseur itérateur de fenêtre en Python] (http://stackoverflow.com/q/6822725) –

+0

J'ai juste ajouté le point de départ et l'étape selon la documentation islise https: // docs. python.org/2/library/itertools.html#itertools.islice – Polly

+0

Mais pourquoi? Vous n'avez pas besoin d'une taille de pas. Laissez-le à 1. –

Répondre

3

Votre version est incorrecte. Il ajoute un 4ème argument (la taille de l'étape) à la fonction islice() qui limite la taille de la première tranche prise va être:

result = tuple(islice(it, 0, window_size, round(window_size/4))) 

Pour 4 ou 5, round(window_size/4) produit 1, la taille de pas par défaut. Mais pour des valeurs plus grandes, ceci produit une taille de pas qui garantit que les valeurs seront omises de cette première fenêtre, ainsi le test suivant, len(result) == window_size est garanti être faux. Supprimez cet argument de taille de pas et vous obtiendrez votre première fenêtre à nouveau. Voir aussi Rolling or sliding window iterator in Python.

Le premier résultat est entre «crochets» car il s'agit d'un tuple. Si vous voulez une liste à la place, utilisez list() plutôt que tuple() dans votre code.

Si vous souhaitez que votre fenêtre glisse par incréments supérieurs à 1, vous ne devez pas modifier la fenêtre initiale. Vous devez ajouter et supprimer des éléments de taille step de la fenêtre pendant que vous effectuez une itération. Ce qui est fait plus facile avec une boucle while:

def window_with_larger_step(fseq, window_size): 
    """Sliding window 

    The step size the window moves over increases with the size of the window. 
    """ 
    it = iter(fseq) 
    result = list(islice(it, 0, window_size)) 
    if len(result) == window_size: 
     yield result 
    step_size = max(1, int(round(window_size/4))) # no smaller than 1 
    while True: 
     new_elements = list(islice(it, step_size)) 
     if len(new_elements) < step_size: 
      break 
     result = result[step_size:] + list(islice(it, step_size)) 
     yield result 

Cela ajoute step_size éléments au résultat courant, la suppression step_size éléments du début à maintenir la taille de la fenêtre même.

Démo:

>>> print(list(window_with_larger_step(c, 6))) 
[['A', 'B', 'C', 'D', 'E', 'F'], ['C', 'D', 'E', 'F', 'I', 'J'], ['E', 'F', 'I', 'J', 'M', 'N'], ['I', 'J', 'M', 'N', 'Q', 'R'], ['M', 'N', 'Q', 'R', 'U', 'V'], ['Q', 'R', 'U', 'V', 'Y', 'Z']] 
>>> print(list(window_with_larger_step(c, 8))) 
[['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H'], ['C', 'D', 'E', 'F', 'G', 'H', 'K', 'L'], ['E', 'F', 'G', 'H', 'K', 'L', 'O', 'P'], ['G', 'H', 'K', 'L', 'O', 'P', 'S', 'T'], ['K', 'L', 'O', 'P', 'S', 'T', 'W', 'X'], ['O', 'P', 'S', 'T', 'W', 'X']] 
>>> print(list(window_with_larger_step(c, 10))) 
[['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J'], ['D', 'E', 'F', 'G', 'H', 'I', 'J', 'N', 'O', 'P'], ['G', 'H', 'I', 'J', 'N', 'O', 'P', 'T', 'U', 'V'], ['J', 'N', 'O', 'P', 'T', 'U', 'V', 'Z']]