Ich habe eine Liste von Tupeln wie unten gezeigt. Ich muss zählen, wie viele Elemente eine Nummer größer als 1 haben. Der Code, den ich bisher geschrieben habe, ist sehr langsam. Selbst wenn es etwa 10K-Tupel gibt, wenn Sie unter Beispiel sehen, erscheint String zweimal, also muss ich solche Saiten bekommen. Meine Frage ist, wie man die Anzahl der Zeichenfolgen hier am besten durch Iteration über den Generator erreichen kann
Liste:
b_data=[('example',123),('example-one',456),('example',987),.....]
Mein Code bisher:
blockslst=[]
for line in b_data:
blockslst.append(line[0])
blocklstgtone=[]
for item in blockslst:
if(blockslst.count(item)>1):
blocklstgtone.append(item)
Sie haben die richtige Idee, den ersten Gegenstand aus jedem Tupel zu extrahieren. Sie können Ihren Code anhand eines Listen-/Generator-Verständnisses präziser gestalten, wie ich Ihnen im Folgenden zeige.
Von diesem Punkt an ist die idiomatischste Art, Frequenzzählungen von Elementen zu finden, die Verwendung eines collections.Counter
-Objekts.
Counter
example
from collections import Counter
counts = Counter(x[0] for x in b_data)
print(counts['example'])
Natürlich können Sie list.count
verwenden, wenn es sich nur um einen - one - Eintrag handelt, für den Sie Häufigkeitszahlen suchen möchten, aber im Allgemeinen ist eine Counter
der Weg.
Der Vorteil einer Counter
ist, dass sie Frequenzzählungen von all -Elementen (nicht nur example
) in linearer (O(N)
) Zeit durchführt. Angenommen, Sie wollten auch die Anzahl eines anderen Elements abfragen, beispielsweise foo
. Das wäre mit -
print(counts['foo'])
Wenn 'foo'
nicht in der Liste vorhanden ist, wird 0
zurückgegeben.
Wenn Sie die am häufigsten verwendeten Elemente suchen möchten, rufen Sie counts.most_common
auf.
print(counts.most_common(n))
Dabei ist n
die Anzahl der Elemente, die Sie anzeigen möchten. Wenn Sie alles sehen wollen, übergeben Sie nicht n
.
Um die Anzahl der am häufigsten verwendeten Elemente abzurufen, ist es eine effiziente Möglichkeit, most_common
abzufragen und dann alle Elemente mit einer Anzahl über 1 effizient mit itertools
zu extrahieren.
from itertools import takewhile
l = [1, 1, 2, 2, 3, 3, 1, 1, 5, 4, 6, 7, 7, 8, 3, 3, 2, 1]
c = Counter(l)
list(takewhile(lambda x: x[-1] > 1, c.most_common()))
[(1, 5), (3, 4), (2, 3), (7, 2)]
(OP-Bearbeitung) Alternativ können Sie ein Listenverständnis verwenden, um eine Liste der Elemente mit der Anzahl> 1 - zu erhalten.
[item[0] for item in counts.most_common() if item[-1] > 1]
Beachten Sie, dass dies nicht so effizient ist wie die itertools.takewhile
-Lösung. Wenn Sie beispielsweise ein Element mit einer Zählung> 1 und eine Million Elemente mit einer Zählung von 1 haben, werden Sie am Ende eine Million und einmal durchlaufen, wenn Sie nicht müssen (weil most_common
die Häufigkeit zurückgibt zählt in absteigender Reihenfolge). Bei takewhile
ist dies nicht der Fall, da Sie die Iteration beenden, sobald die Bedingung für count> 1 falsch wird.
Erste Methode:
Was ist ohne Schleife?
print(list(map(lambda x:x[0],b_data)).count('example'))
ausgabe:
2
Zweite Methode:
Sie können mit Simple Dict berechnen, ohne ein externes Modul zu importieren oder es so komplex zu gestalten:
b_data = [('example', 123), ('example-one', 456), ('example', 987)]
dict_1={}
for i in b_data:
if i[0] not in dict_1:
dict_1[i[0]]=1
else:
dict_1[i[0]]+=1
print(dict_1)
print(list(filter(lambda y:y!=None,(map(lambda x:(x,dict_1.get(x)) if dict_1.get(x)>1 else None,dict_1.keys())))))
ausgabe:
[('example', 2)]
Testfall :
b_data = [('example', 123), ('example-one', 456), ('example', 987),('example-one', 456),('example-one', 456),('example-two', 456),('example-two', 456),('example-two', 456),('example-two', 456)]
ausgabe:
[('example-two', 4), ('example-one', 3), ('example', 2)]
Zeit, die ich dafür brauchte ayodhyankit-paul hat dasselbe gepostet - es bleibt jedoch nichts anderes übrig für den Generatorcode für Testfälle und Timing:
Das Erstellen von 100001 -Elementen dauerte ungefähr 5 Sekunden, das Zählen dauerte ungefähr 0,3s, Das Filtern nach Zählungen war zu schnell zum Messen (mit datetime.now () - hat sich nicht mit perf_counter beschäftigt. ) - Alles in allem hat es von Anfang bis Ende weniger als 5,1s für ungefähr das 10-fache der Daten gedauert, mit denen Sie arbeiten.
Ich denke, das ähnelt dem, was Counter
in COLDSPEED s antwort macht:
foreach item
in list of tuples
:
item[0]
nicht in der Liste enthalten ist, mit count of 1
in dict
eingeben.increment count
im Dikt by 1
Code:
from collections import Counter
import random
from datetime import datetime # good enough for a loong running op
dt_datagen = datetime.now()
numberOfKeys = 100000
# basis for testdata
textData = ["example", "pose", "text","someone"]
numData = [random.randint(100,1000) for _ in range(1,10)] # irrelevant
# create random testdata from above lists
tData = [(random.choice(textData)+str(a%10),random.choice(numData)) for a in range(numberOfKeys)]
tData.append(("aaa",99))
dt_dictioning = datetime.now()
# create a dict
countEm = {}
# put all your data into dict, counting them
for p in tData:
if p[0] in countEm:
countEm[p[0]] += 1
else:
countEm[p[0]] = 1
dt_filtering = datetime.now()
#comparison result-wise (commented out)
#counts = Counter(x[0] for x in tData)
#for c in sorted(counts):
# print(c, " = ", counts[c])
#print()
# output dict if count > 1
subList = [x for x in countEm if countEm[x] > 1] # without "aaa"
dt_printing = datetime.now()
for c in sorted(subList):
if (countEm[c] > 1):
print(c, " = ", countEm[c])
dt_end = datetime.now()
print( "\n\nCreating ", len(tData) , " testdataitems took:\t", (dt_dictioning-dt_datagen).total_seconds(), " seconds")
print( "Putting them into dictionary took \t", (dt_filtering-dt_dictioning).total_seconds(), " seconds")
print( "Filtering donw to those > 1 hits took \t", (dt_printing-dt_filtering).total_seconds(), " seconds")
print( "Printing all the items left took \t", (dt_end-dt_printing).total_seconds(), " seconds")
print( "\nTotal time: \t", (dt_end- dt_datagen).total_seconds(), " seconds" )
Ausgabe:
# reformatted for bevity
example0 = 2520 example1 = 2535 example2 = 2415
example3 = 2511 example4 = 2511 example5 = 2444
example6 = 2517 example7 = 2467 example8 = 2482
example9 = 2501
pose0 = 2528 pose1 = 2449 pose2 = 2520
pose3 = 2503 pose4 = 2531 pose5 = 2546
pose6 = 2511 pose7 = 2452 pose8 = 2538
pose9 = 2554
someone0 = 2498 someone1 = 2521 someone2 = 2527
someone3 = 2456 someone4 = 2399 someone5 = 2487
someone6 = 2463 someone7 = 2589 someone8 = 2404
someone9 = 2543
text0 = 2454 text1 = 2495 text2 = 2538
text3 = 2530 text4 = 2559 text5 = 2523
text6 = 2509 text7 = 2492 text8 = 2576
text9 = 2402
Creating 100001 testdataitems took: 4.728604 seconds
Putting them into dictionary took 0.273245 seconds
Filtering donw to those > 1 hits took 0.0 seconds
Printing all the items left took 0.031234 seconds
Total time: 5.033083 seconds
Ich möchte Ihnen ein Beispiel geben, um Sie verständlich zu machen. Obwohl dieses Beispiel sich sehr von Ihrem Beispiel unterscheidet, fand ich es sehr hilfreich beim Lösen dieser Art von Fragen.
from collections import Counter
a = [
(0, "Hadoop"), (0, "Big Data"), (0, "HBase"), (0, "Java"),
(1, "Postgres"), (2, "Python"), (2, "scikit-learn"), (2, "scipy"),
(2, "numpy"), (2, "statsmodels"), (2, "pandas"), (3, "R"), (3, "Python"),
(3, "statistics"), (3, "regression"), (3, "probability"),
(4, "machine learning"), (4, "regression"), (4, "decision trees"),
(4, "libsvm"), (5, "Python"), (5, "R"), (5, "Java"), (5, "C++"),
(5, "Haskell"), (5, "programming languages"), (6, "statistics"),
(6, "probability"), (6, "mathematics"), (6, "theory"),
(7, "machine learning"), (7, "scikit-learn"), (7, "Mahout"),
(7, "neural networks"), (8, "neural networks"), (8, "deep learning"),
(8, "Big Data"), (8, "artificial intelligence"), (9, "Hadoop"),
(9, "Java"), (9, "MapReduce"), (9, "Big Data")
]
#
# 1. Lowercase everything
# 2. Split it into words.
# 3. Count the results.
dictionary = Counter(Word for i, j in a for Word in j.lower().split())
print(dictionary)
# print out every words if the count > 1
[print(Word, count) for Word, count in dictionary.most_common() if count > 1]
Nun ist dies Ihr Beispiel, das auf die obige Weise gelöst wurde
from collections import Counter
a=[('example',123),('example-one',456),('example',987),('example2',987),('example3',987)]
dict = Counter(Word for i,j in a for Word in i.lower().split() )
print(dict)
[print(Word ,count) for Word,count in dict.most_common() if count > 1 ]