-2

I'm trying to find the co shortest words and co longest words in a given dictionary with the keys being the words. When I sort the dictionary, my code below doesn't do that. I get "And" for shorts and "yours" for longs. What is the problem?

def build_report(freq):
    report={}
    #for shorts:
    sorted(freq.keys())
    print(sorted(freq.keys()))
    shortest=sorted(freq.keys())[0]
    shorts=list()
    shorts.append(shortest)
    print(shorts)
    report["shorts:"]=shorts
    #for longs:
    longest=sorted(freq.keys(),reverse=True)[0]
    print(sorted(freq.keys(),reverse=True))
    longs=list()
    longs.append(longest)
    print(longs)
    report["longs:"]=longs

This is the freq I'm inputting:

freq={'I': 1, 'heaven': 1, 'filled': 1, 'their': 1, 'termed': 1, 'of': 4, 'And': 3, 'parts': 1, 'neer': 1, 'to': 2, 'song': 1, 'poets': 1, 'The': 1, 'a': 2, 'were': 2, 'verse': 1, 'your': 6, 'knows': 1, 'not': 1, 'half': 1, 'number': 1, 'but': 1, 'yours': 1, 'come': 2, 'rage': 1, 'age': 2, 'Though': 1, 'men': 1, 'fresh': 1, 'heavenly': 1, 'say': 1, 'alive': 1, 'truth': 1, 'this': 1, 'If': 2, 'than': 1, 'old': 1, 'believe': 1, 'Which': 1, 'that': 1, 'You': 1, 'faces': 1, 'yet': 1, 'poet': 1, 'in': 4, 'life': 1, 'most': 1, 'earthly': 1, 'will': 1, 'hides': 1, 'my': 3, 'papers': 1, 'is': 1, 'stretched': 1, 'rights': 1, 'eyes': 1, 'it': 3, 'yellowed': 1, 'Such': 1, 'So': 1, 'all': 1, 'lies': 1, 'the': 1, 'an': 1, 'as': 1, 'write': 1, 'child': 1, 'deserts': 1, 'shows': 1, 'tongue': 1, 'twice': 1, 'Be': 1, 'high': 1, 'some': 1, 'could': 1, 'should': 2, 'and': 2, 'touched': 1, 'like': 1, 'would': 1, 'Who': 1, 'tomb': 1, 'numbers': 1, 'antique': 1, 'scorned': 1, 'metre': 1, 'time': 2, 'touches': 1, 'be': 1, 'with': 2, 'true': 1, 'beauty': 1, 'rhyme': 1, 'less': 1, 'But': 1, 'graces': 1, 'live': 1}
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
user2976821
  • 353
  • 1
  • 3
  • 8

1 Answers1

5

You are sorting your keys lexicographically (i.e. alphabetically), not by length.

You are also sorting them way too often. Sort just once, on length:

keys = sorted(freq, key=len)
shortest, longest = keys[0], keys[-1]

Because a dictionary, when iterated over, produces just the keys, you don't even need to call .keys() here.

Demo:

>>> keys = sorted(freq, key=len)
>>> shortest, longest = keys[0], keys[-1]
>>> shortest
'I'
>>> longest
'stretched'

If you need all words of the same length as the first:

shortest = [keys[0]]
for key in keys[1:]:
    if len(key) == len(shortest[0]):
        shortest.append(key)
    else:
        break
longest = [keys[-1]]
for key in reversed(keys[:-1]):
    if len(key) == len(longest[0]):
        longest.append(key)
    else:
        break

or a little more advanced, using itertools.groupby():

from itertools import groupby
keys = sorted(freq, key=len)
shortest = list(next(groupby(keys, key=len))[1])
longest = list(next(groupby(reversed(keys), key=len))[1])
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • @JonClements: Uhm, yes, yes, indeed, I totally was. (thanks). – Martijn Pieters Nov 22 '13 at 15:42
  • how can you get the shortest words of the same length? I tried using a for loop and comparing the length of each key which I put into a list first but that didn't work either. – user2976821 Nov 22 '13 at 15:52
  • `[x for x in keys if len(x) == len(shortest)]` would be a list of the shortest words if `shortest` is a string of the shortest word in keys – TehTris Nov 22 '13 at 16:53
  • @TehTris: but would loop through **all** keys, which being in length-sorted order, is a bit of a waste. – Martijn Pieters Nov 22 '13 at 16:58
  • @MartijnPieters if iterating through a list the size of OPs, then that time/memory wasted is negligible. Definately use the `break` if enormous lists are involved though. – TehTris Nov 22 '13 at 17:02