it-swarm.com.de

Top "n" Einträge in einem Wörterbuch drucken

Hier ist mein aktueller Code

pN ={'dave': 10, 'jacinta': 10, 'james': 8, 'john': 6, 'jack': 3, 'sam': 2}
highestCount = max(pN.values())

for k, v in pN.items():
  if v == highestCount:
    print(v,k)

Dies druckt jedoch nur den ersten Benutzer und wenn diese Position freigegeben ist, wird sie erneut als solche gedruckt

10 dave
10 jacinta

Ich muss in der Lage sein, eine beliebige Anzahl von Top-Benutzern (n) zu drucken und als solche formatieren zu lassen, z. für n = 5:

10 john, jacinta, 
8 james
6 john
3 jack
2 sam
13
user9814201

Verwenden Sie einen collections.defaultdict , tauschen Sie Ihre keys und values aus.

from collections import defaultdict
dct = defaultdict(list)

for k, v in pN.items():
  dct[v].append(k)

# defaultdict(<class 'list'>, {10: ['dave', 'jacinta'], 8: ['james'], 6: ['john'], 3: ['jack'], 2: ['sam']})

Verwenden Sie sorted für die Ausgabe:

for k, v in sorted(dct.items(), reverse=True):
  print(k, ', '.join(v))

# Result

10 dave, jacinta
8 james
6 john
3 jack
2 sam

function, um die obersten n Benutzer zurückzugeben (Bindungen werden als ein Eintrag behandelt):

def top_n(d, n):
  dct = defaultdict(list) 
  for k, v in d.items():
    dct[v].append(k)      
  return sorted(dct.items())[-n:][::-1]

top_n(pN, 3)

# [(10, ['dave', 'jacinta']), (8, ['james']), (6, ['john'])]

Die Verwendung einer defaultdict ist einfach und schnell. Hier sind einige Zeitangaben, um dies zu beweisen:

Funktionen, die zeitgesteuert werden

def chris_z(d, n):
  dct = defaultdict(list) 
  for k, v in d.items():
    dct[v].append(k)      
  return sorted(dct.items())[-n:][::-1]

def tim_lombard(score_dict, n):
  lot = [(k,v) for k, v in score_dict.items()] #make list of Tuple from scores dict
  nl = []
  while len(lot)> 0:
      nl.append(max(lot, key=lambda x: x[1]))
      lot.remove(nl[-1])

def ajax(d, n:'n_users', top = True):
  _ranks = sorted(d.values())
  _ranks = _ranks[-n:] if top else _ranks[:n]
  return {i:[a for a, b in d.items() if b == i] for i in _ranks}

Ergebnisse

x = [''.join(i) for i in itertools.permutations('chrisz', 6)]    
y = [random.randint(0, 100) for _ in range(720)]  
z = dict(Zip(x, y))

In [40]: %timeit chris_z(z, 500)
110 µs ± 259 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

In [42]: %timeit tim_lombard(z, 500)
26.2 ms ± 60 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

In [43]: %timeit ajax(z, 500)
15.3 ms ± 227 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
11
user3483203

Würde das für dich funktionieren? 

pN ={'dave': 10, 'jacinta': 10, 'james': 8, 'john': 6, 'jack': 3, 'sam': 2}

def top_n_scores(n, score_dict):
  ''' returns the n scores from a name:score dict'''
  lot = [(k,v) for k, v in pN.items()] #make list of Tuple from scores dict
  nl = []
  while len(lot)> 0:
      nl.append(max(lot, key=lambda x: x[1]))
      lot.remove(nl[-1])

  return nl[0:n]   

Um die besten 4 Punkte zu erhalten:

top_n_scores(4, pN) 

[('dave', 10), ('jacinta', 10), ('james', 8), ('john', 6)]
1
Timothy Lombard

Sie können sorted und ein Wörterbuchverständnis verwenden:

from typing import Dict, List
def ranking(d, n:'n_users', top = True) -> Dict[int, List[str]]:
  _ranks = sorted(d.values())
  _ranks = _ranks[-n:] if top else _ranks[:n]
  return {i:[a for a, b in d.items() if b == i] for i in _ranks}

pN ={'dave': 10, 'jacinta': 10, 'james': 8, 'john': 6, 'jack': 3, 'sam': 2}
for a, b in sorted(ranking(pN, 10).items(), key=lambda x:x[0], reverse=True):
  print('{} {}'.format(a, ', '.join(b)))

Ausgabe:

10 dave, jacinta
8 james
6 john
3 jack
2 sam

Bearbeiten: Für eine beliebige Anzahl von Top-Benutzern übergeben Sie den Wert an die Funktion:

_r = ranking(pN, 5) #for the top 5 users
1
Ajax1234

Sie sollten es mit collections.defaultdict mit eingebauter sorted()-Funktion versuchen.

from collections import defaultdict

def sort_it(_dict, n):
    result = defaultdict(list)
    for name, num in _dict.items():
        result[num].append(name)
    return sorted(result.items(), reverse=True)[:n]

>>> pN = {'dave': 10, 'jacinta': 10, 'james': 8, 'john': 6, 'jack': 3, 'sam': 2}
>>> top3 = sort_it(pN, 3)
[(10, ['jacinta', 'dave']), (8, ['james']), (6, ['john'])] # Output
0
Bijoy

Da Sie nach Ergebnissen gruppieren möchten, ist es sinnvoll, itertools.groupby zu verwenden:

scores ={'dave': 10, 'jacinta': 10, 'james': 8, 'john': 6, 'jack': 3, 'sam': 2}

from itertools import groupby
from operator import itemgetter

get_score = itemgetter(1)

def group_users_by_score(scores, n=-1):
    sorted_users = sorted(scores.items(), key=get_score, reverse=True)
    top_n = sorted_users[:n]
    return groupby(top_n, key=get_score)

def display_top_users(scores, n=-1):
    for score, users in group_users_by_score(scores, n):
        print("%3d %s" % (score, ', '.join(u for (u,s) in users)))

Als Beispiel:

>>> display_top_users(scores, 3)
 10 dave, jacinta
  8 james
>>> display_top_users(scores)
 10 dave, jacinta
  8 james
  6 john
  3 jack
0
Eric Duminil