it-swarm.com.de

Zählhäufigkeit eines Elements in einer Liste von Tupeln

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)
13
min2bro

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.

  1. Extrahieren Sie die ersten Elemente aus Ihrer Liste von Tupeln (unter Verwendung eines Verständnisses).
  2. Übergeben Sie dies an Counter
  3. Abfrageanzahl von 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.

12
coldspeed

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)]
2
Aaditya Ura

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:

  • wenn item[0] nicht in der Liste enthalten ist, mit count of 1 in dict eingeben.
  • sonst 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 
2
Patrick Artner

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  ]
0
Soudipta Dutta