9
votes

Python: Quel est le moyen le plus rapide de zip à gauche à gauche et n'y a-t-il pas intégré pour cela?

donné 2 séquences de différentes longueurs: xxx

c'est ce que je veux xxx

mais je n'aime pas l'idée de En utilisant à l'envers toutes mes paramètres d'entrée, et je ne veux pas non plus ré-implémenter ma propre fonction zip.

SO:

  1. Y a-t-il un moyen plus rapide / plus efficace de faire cela?
  2. Y a-t-il un moyen plus simple de faire cela?

5 commentaires

Quel est faux avec zip (inversé (A), inversé (B)) ? Il est court, rapide et expressif (dit ce que cela signifie). Aucune des autres solutions proposées n'est aussi concise, aussi rapide, aussi claire que ce que vous avez commencé.


@RayMondhettinger - Le problème est qu'il veut maintenir l'ordre d'origine, mais en prenant les éléments les plus puissants de la liste plus grande. Il aurait besoin d'une autre chose comme la liste (inversée (zip (inverse (A), inversée (B))) ou la compréhension de la liste dans la question.


Même zip (inversé (A), inversé (B)) [:: - 1] est plus clair et plus rapide que les solutions postées.


Je pense que la principale à emporter est que nous pouvons choisir parmi les nombreuses façons de le faire, et il n'y a pas nécessairement une bonne réponse. Ce qui est juste pour le moment peut dépendre des choses comme combien de séquences d'intrants sont en cours de zipper ou si des personnes peuvent avoir besoin de comprendre le code après le fait, etc.


Du inversé (liste (Zip (A, B))) ?


6 Réponses :


4
votes

Je suggérerais:

>>> a = [1,2,3]
>>> b = [4,5,6,7]
>>> k = min(len(a),len(b))
>>> zip(a[-k:], b[-k:])
[(1, 5), (2, 6), (3, 7)]


5 commentaires

Beaucoup mieux. Je rétracte ma réponse, humilié :)


@IM: Dans toute l'équité, j'ai initialement écrit "Len (A) -K" au lieu de "-k" et a adapté ma réponse après avoir vu le vôtre, alors merci.


Oui, c'est une bonne réponse. Merci!


Ou utilisez ithertools.lice pour éviter de prendre une copie de la liste, mais que vous devriez calculer les indices corrects car il ne peut pas prendre de valeurs négatives.


Calcul des indices lorsque vous n'êtes pas obligé de ne pas être la méthode «Pythonic».



0
votes
zip(a[len(a)-min(len(a), len(b)):], b[len(b)-min(len(a), len(b)):])
but it does not look very "pythonic" :P

0 commentaires

3
votes

Ce qui suit fonctionnera même si vous ne savez pas ce qui est plus long:

>>> range(5)[-10:]
[0, 1, 2, 3, 4]


3 commentaires

J'aime ça même mieux: p


Cette réponse est intelligente, mais est trop délicate pour être considérée comme pythonique. Il serait difficile de maintenir (quiconque lisant le code doit faire un peu de déchiffrement et de perplexe pour se convaincre que le code est correct). De plus, pour de longues entrées, il n'est pas sympathique de la mémoire et fait beaucoup de copier.


Cela ne généralisera pas facilement à 3 listes ou plus, cependant.



0
votes

[Mise à jour pour ajouter une possibilité de commander inversé (car je pensais que je pouvais utiliser ceci un jour)]

en tant que générateur, vous pouvez essayer, xxx < / pré>

Ce n'est pas obligé de prendre des copies des listes et donne, xxx


0 commentaires

8
votes

Ce qui suit est plus rapide et plus clair que les autres solutions publiées: xxx

Le inversifié crée un itérateur ces boucles à la même vitesse que vers l'avant itération. Aucun mémoire supplémentaire (des copies complètes de l'entrée) sont produites et il n'y a pas de ralentissement des voyages lents autour du Python Eval-boucle (présent dans les autres solutions qui utilisent des indices).


3 commentaires

Je reçois l'objet 'zip' n'est pas syndicalable et 'zip' objet n'a pas d'attribut 'inverse'


Dans Python 3, zip renvoie un itérateur, vous pouvez donc tout faire en une seule passe et ne convertit que dans une liste à la fin de la liste suivante: Liste (inversée (zip (a inversé (A), inversé (b)))) .


inversé () n'accepte qu'une séquence, quelle que soit la version de Python utilisée. Ensuite, dans Python 2.x, il est Liste (inversée (zip (inverser (A), inversé (b)))) mais dans python 3.x il est Liste (annulée (Zip (inversé (A), inversé (B)))))) Donc, dans les deux cas, il est nécessaire de créer une nouvelle liste intermédiaire lorsqu'une doublure est utilisée.



2
votes

Dans la solution suivante, aucune copie de l'une des listes d'entrée n'est effectuée.

len(a) == 49500
len(b) == 50000

100.00 %     Sam Hocevar, deducted normal slicing and zip
k = min(len(a),len(b))
list(zip(a[-k:], b[-k:]))

99.39 %     F.J. , deducted tricky slicing and zip
list(zip(a[-len(b):], b[-len(a):]))

99.12 %     sleeplessnerd, exactly normal slicing and zip
m = min(len(a),len(b))
list(zip(a[len(a)-m:],b[len(b)-m:]))

98.10 %     Sam Hocevar, exactly normal slicing and zip
k = min(len(a),len(b))
list(zip(a[len(a)-k:], b[len(b)-k:]))

69.91 %     eyquem 1, deducted normal slicing and listcomp
m = min(len(a),len(b))
[ (a[-m+i],b[-m+i]) for i in range(m) ]

66.54 %     eyquem 1 improved, exactly normal slicing and listcomp
m = min(len(a),len(b)
x,y = len(a)-m , len(b)-m
[(a[x+i],b[y+i]) for i in range(m)]

58.94 %     Raymond Hettinger, use of zip and iterator reversed
list(reversed(list(zip(reversed(a),reversed(b)))))

51.29 %     eyquem 2, use of zip and iterator iter
list(zip(ita,itb))

51.17 %     eyquem 3, use of zip and iterators iter AND islice
list(zip(iter(a),islice(b,len(b)-len(a),None)))

sam1==sam2==fj==sleep==ey1==ey1bis==ey2==ey3==ray  is  True


0 commentaires