12
votes

Itération rapide sur les premiers n articles d'une iérente (pas une liste) en python

Je cherche une manière pythonique d'itération sur le premier n code> articles d'un iérent ( upd upd strong>: pas une liste dans un cas commun, comme pour les listes les choses sont trivial), et il est très important de le faire aussi vite que possible. C'est comme ça que je le fais maintenant:

pair_generator = lambda iterable: itertools.izip(*[iter(iterable)]*2)
for item in itertools.islice(pair_generator(iterable), n):
 so_something(item)


3 commentaires

Le seul moyen de répondre "assez rapide" est de le repousser vous-même.


Voir aussi: Stackoverflow.com/Questtions/2688079/...


Pourquoi est-il "très important de le faire aussi vite que possible"? Pouvez-vous justifier cela avec les résultats PSTAT pour un cas d'utilisation réaliste? Je soupçonne que votre solution avec islice prouvera réellement la meilleure solution raisonnable performance-sage, mais bien sûr, nous ne savons pas sans timing.


5 Réponses :


1
votes

d'une liste? Essayez xxx

Vous pouvez également utiliser une compréhension si vous devez xxx


0 commentaires

2
votes

Si c'est une liste, vous pouvez utiliser la tranchée:

list[:n]


0 commentaires

15
votes

pour l'article dans iteroTools.lice (itéroureux, n): est le moyen le plus évident et facile de le faire. Cela fonctionne pour des itérables arbitraires et est O (n), comme une solution sain d'esprit.

Il est concevable qu'une autre solution pourrait avoir une meilleure performance; Nous ne saurions pas sans timing. Je ne recommanderais pas la peine de déranger avec le timing sauf si vous profil votre code et trouvez cet appel à être un hotspot. À moins que ce ne soit enterré dans une boucle intérieure, il est très douteux que ce soit. L'optimisation prématurée est la racine de tout mal.


Si je était allez chercher des solutions alternatives, je regarderais des solutions telles que pour le compte, article en énumérant (iTAKEFIER): Si Comptez> N: Pause ... et pour i in xrange (n): élément = suivant (itérateur) ... . Je ne devrais pas deviner que celles-ci aideraient, mais ils semblent avoir la peine d'être essayé si nous voulons vraiment comparer les choses. Si j'étais coincé dans une situation où j'ai profilé et j'ai trouvé que c'était un point chaud dans une boucle intérieure (est-ce vraiment votre situation?), J'essaierais également de soulager le nom de la recherche du Islice Attribut du global iterools pour lier la fonction à un nom local déjà.

Ce sont des choses que vous ne faites que après que vous aviez prouvé qu'ils vous aideront. Les gens essaient de les faire d'autres fois. Cela ne vous aide pas à rendre leurs programmes sensiblement plus rapidement; Cela fait pire leurs programmes.


2 commentaires

Merci beaucoup pour la réponse, cela m'a beaucoup aidé!


Eh bien, un peu énuméré a l'air assez bon pour moi aussi! En ce qui concerne le profilage et la recherche de points chauds, ce n'est pas réellement mon cas, je m'attends à ce que certaines boucles dans mon code d'avoir énormément comptent une itération, c'est pourquoi j'ai posé une question. Maintenant, je l'obtiens - c'était une erreur d'essayer d'optimiser sur cette étape, je dois terminer le code et le tester, puis optimiser les choses, si nécessaire. Merci encore pour votre aide.



6
votes

iTertools a tendance à être la solution la plus rapide, lorsqu'il est directement applicable.

évidemment, le seul moyen de vérifier est de repasser - économiser dans aaa.py xxx

et voir ...: xxx

si clairement, iTerTools est plus rapide ici - référence avec votre propre Données à vérifier.

BTW, je trouve Timeit beaucoup plus utilisable de la ligne de commande, c'est ainsi que je l'utilise toujours - il exécute alors le bon "ordre de grandeur" des boucles pour le type de vitesse, vous essayez spécifiquement de mesurer, que ce soit ces 10, 100, 1000, etc. Ici, pour distinguer un microseconde et une demi-différence, cent mille boucles est à peu près correcte.


2 commentaires

Beird, c'est juste contre mon intuition Cplusplus'ish de voir une solution simple courir plus lentement qu'une solution soignée. Python est la langue la plus cool, en effet. C'est un excellent ajout aux conseils de Mike Graham pour ne pas procéder à une optimisation prématurée. Je suppose que la règle générale est d'écrire ce qui est soigné et ne pense pas à la course à pied.


@martin, personnellement, je pense qu'un lot sur le temps de course (principalement en termes de big-o pour l'évolutivité) - mais, en général, les idiomes les plus pythoniques vont souvent être ceux qui ont souvent ceux qui ont été le plus optimisé, car ils sont généralement ceux qui sont généralement des prisonniers Python américains ont tendance à prendre en charge le plus (Hettinger, l'auteur d'itoTools et d'autres parties rapides de Python, a été assez active dans ce domaine ces dernières années, de même que des péters dans les années précédentes. , mais c'est un phénomène assez général dans la communauté du commissateur Python).



2
votes

Vous pouvez utiliser énumérer pour écrire essentiellement la même boucle que vous avez, mais de manière plus simple, pythonique: xxx


1 commentaires

Cette option a été discutée ci-dessus, ressemble à une bonne option, mais je pense que islice est meilleur car il ne nécessite aucune variables supplémentaires dans le corps de la boucle, ce qui le rend plus clair pour moi.