Python logic help – Print the top “n” users

  • A+
Category:Languages

Here's my current 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) 

However this only prints the top user and if that position is shared, prints it again as such

10 dave 10 jacinta 

I need to be able to print any amount of top users (n) and have it formatted as such, e.g. for n = 5:

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


Use a collections.defaultdict, swap your keys and values

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']}) 

Use sorted for output:

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 to return top n users (treats ties as one entry):

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'])] 

Using a defaultdict is simple and fast, and here are some timings to prove it:

Functions that will be timed

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} 

Results

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) 

Comment

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: