'How to account for ties in returning top n values?

I have a dictionary of top values that I have collected from Twitter, here's a small example:

{'aberdeen': 5,
 'amsterdam': 6,
 'amsterdam?fussa': 6,
 'anchorage': 12,
 'andalucia?granada': 5,
 'ann arbor': 6,
 'aral': 6,
 'arlington': 6,
 'asia?london': 6,

I have two functions of returning the top 'n' results:

def top_items(item_counts, n=3):
    counts = Counter(item_counts)
    most_common = counts.most_common(n)
    for item in zip(*most_common):
        return list(item)

and

def top_items2(item_counts, n=3):
  top_count = sorted(item_counts.items(), key=lambda x: x[1], reverse=True)[:n]
  return [x[0] for x in top_count]

Both retrieve the top n results. However, I'm having issues trying to account for ties. In this example, the top cities are ['los angeles', 'chicago', 'denver'], however denver and nyc both have a count of 8, but it returns denver because its first alphabetically.

How could I edit my code to return the keys of my dictionary of the top n values including ties?

Thanks!



Solution 1:[1]

You can first find the top values by sorting and compare them to all the values:

di = {'aberdeen': 5,
      'amsterdam': 6,
      'amsterdam?fussa': 6,
      'anchorage': 12,
      'andalucia?granada': 5,
      'ann arbor': 6,
      'aral': 6,
      'arlington': 6,
      'asia?london': 6
      }

def getTopResults(di: dict, n):
    final = {}
    topValues = sorted(di.values())[:n+1]
    for k, v in di.items():
        if v in topValues:
            final[k] = v

    return final

print(getTopResults(di, 2)) # {'aberdeen': 5, 'amsterdam': 6, 'amsterdam?fussa': 6, 'andalucia?granada': 5, 'ann arbor': 6, 'aral': 6, 'arlington': 6, 'asia?london': 6}

Solution 2:[2]

This function does same in a recursive way, assuming input list is already sorted in asc or desc order:

get_next(3, [])
get_next(3, [1,2,3,4,5])
get_next(3, [1,1,1,1,1,2,2,3,4,5,6])
get_next(3, [1,2,2,2,2,3,4,5])

def get_next(n,xs, last=None):
    if len(xs)>0:
        head, *tail=xs
        if head == last:
            n+=1 # need to go 1 further if tie
        if n>0:
            return [head] + get_next(n-1, tail, head)
    return []

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Shivam Jha
Solution 2 vis