2014-11-28 8 views
7

Ich benutze heapq, um die größten Elemente aus der Liste der Listen zu bekommen. Das Programm, das ich geschrieben habe, ist unten.Wie bekomme ich n größten Listen aus einer Liste von Listen in Python

import csv 
import heapq 
f = open("E:/output.csv","r") 
read = csv.reader(f) 

allrows = [row for row in read] 

for i in xrange(0,2): 
    print allrows[i] 

allrows.sort(key=lambda x: x[2]) #this is working properly 
it=heapq.nlargest(20,enumerate(allrows),key=lambda x:x[2]) #error 

Ich möchte nur die Top 20 Elemente. Anstatt zu sortieren, dachte ich an einen Haufen. Der Fehler, den ich erhalte, ist

Traceback (most recent call last): 
File "D:\eclipse_progs\DaDv\IMDB\Assignment1.py", line 42, in <module> 
    it=heapq.nlargest(2,enumerate(allrows),key=lambda x:x[2]) 
File "C:\Python27\lib\heapq.py", line 470, in nlargest 
    result = _nlargest(n, it) 
File "D:\eclipse_progs\DaDv\IMDB\Assignment1.py", line 42, in <lambda> 
    it=heapq.nlargest(2,enumerate(allrows),key=lambda x:x[2]) 
IndexError: tuple index out of range 

Kann ich wissen, warum ich den Fehler bekomme und wie man es löst. Gibt es eine Eigenschaft von heapq, die ich vermisse?

+0

was ist die Länge Ihrer Zeilen? sind das gleiche? – Kasramvd

+0

Ja, sie sind Größe 4. Alle von ihnen. – WannaBeCoder

Antwort

2

enumerate() gibt einen iterable über 2-Tupel. Daher wird der Zugriff auf x[2] in Ihrem zweiten Beispiel immer außerhalb des Bereichs liegen (die einzigen gültigen Indizes sind 0 und 1).

dem zweiten Beispiel entspricht dem ersten zu machen, sollten Sie allrows direkt statt enumerate() verwenden werden vorbei:

it = heapq.nlargest(20, allrows, key=lambda x:x[2]) 

Wenn Sie die ursprünglichen Indizes beibehalten müssen, enumerate() ist der Weg zu gehen. Sie jedoch auch eine zusätzliche Dereferenzierungsebene in der Schlüsselfunktion benötigen:

it = heapq.nlargest(20, enumerate(allrows), key=lambda x:x[1][2]) 
         ^^^^^^^^^       ^^^ 
+0

Ich verstehe es jetzt. Th Enumerator gibt ein Tupel zurück. also x [1] [2]. Ich wollte auch die Indizes, also habe ich enumeriert. – WannaBeCoder

2

Dank NPE für die Beleuchtung des Problems Als Alternative Antwort, die Sie alle Ihre Zeilen mit itertools.chain() und bekommen Top-20-Element mit Sortier verketten kann, dass mehr Leistung als heapq hat:

from itertools import chain 

sorted(chain(*allrows))[-20:] 

Die nlargest() und nsmallest() Funktionen sind am besten geeignet, wenn Sie findet eine relativ kleine Anzahl von Elementen versuchen. Wenn Sie nur versuchen, die kleinste oder größte Element (N=1) zu finden, ist es schneller min() und max() zu verwenden. In ähnlicher Weise ist es, wenn N ungefähr gleich ist, dieselbe Größe wie die Sammlung selbst, es ist normalerweise schneller, sie zuerst zu sortieren und eine Scheibe zu nehmen (d. H. Verwendung sorted(items)[:N] oder sorted(items)[-N:]).

+0

Es wäre schön, einige Benchmarks zu sehen, um die Leistungsansprüche zu belegen (diese Dinge sind oft voller Überraschungen). – NPE

+0

@kasra OP fragt nicht nach der Lösung, wie man die 20 besten Elemente bekommt, er fragt nach dem Fehler, den er bekommt. –

+0

@ VishnuUpadhyay ja, obwohl das nicht mein qsn war. Davon wusste ich bis jetzt nichts. Also danke Kasara. – WannaBeCoder

Verwandte Themen