For me, the magic of Python is evident in this one-liner (magic line in comments):
dictionary_sorted = ({1: 'one', 2: 'two', 3: 'three', 4: 'four', 5: 'five', 6: 'six', 7: 'seven', 8: 'eight', 9: 'nine', 10: 'ten'})
dictionary_mixed = ({5: 'five', 3: 'three', 7: 'seven', 1: 'one', 10: 'ten', 4: 'four', 9: 'nine', 6: 'six', 2: 'two', 8: 'eight'})
dictionary = dictionary_mixed
# Begin magic line
sortedKeyList = sorted(dictionary.keys(), key=lambda s: len(dictionary.get(s)))
# End magic line
for index in xrange(len(sortedKeyList)):
print("{}: {}".format(sortedKeyList[index], dictionary[sortedKeyList[index]]))
A few takeaways (for those reading):
- You cannot sort a dictionary because they have no concept of order
- Lists CAN be sorted because order is in their nature
- The
sorted()
function returns an iterable (list), which by default is a list sorted by increasing value (unless you include optional reverse=True
argument). Here, we are asking that value to be the length of the dict's value for each key. We sort the keys to get the values back later for printing.
- Again, the dictionary data structure by nature has no concept of order as in Python's dict and the interviewer specifically requested the output to be printed, not returned, for this reason.
- If you still want to satisfy your itch, you can implement a high-performance sort algorithm (i.e. merge sort) using Python's collections.OrderedDict() and then simply print in-order. Yet, again, you'd be sorting more than you need because you really just need the keys.
In any case, an interviewer should love this Pythonic one-liner approach :)
EDIT: If you want to sort the results by key in case multiple value lengths are equal, you could use a while loop. The full code would be:
dictionary_sorted = ({1: 'one', 2: 'two', 3: 'three', 4: 'four', 5: 'five', 6: 'six', 7: 'seven', 8: 'eight', 9: 'nine', 10: 'ten'})
dictionary_mixed = ({5: 'five', 3: 'three', 7: 'seven', 1: 'one', 10: 'ten', 4: 'four', 9: 'nine', 6: 'six', 2: 'two', 8: 'eight'})
dictionary = dictionary_mixed
# Begin magic line
sortedKeyList = sorted(dictionary.keys(), key=lambda s: len(dictionary.get(s)))
# End magic line
# BEGIN sort by keys if values are equal
beg_eq_vals_index = 0
end_eq_vals_index = 0
cur_val = -1
while end_eq_vals_index < len(sortedKeyList):
if len(dictionary[sortedKeyList[end_eq_vals_index]]) > cur_val > -1:
# Replace slice of key list with sorted key list slice
sortedKeyList[beg_eq_vals_index:end_eq_vals_index] = sorted(sortedKeyList[beg_eq_vals_index:end_eq_vals_index])
# Update beginning index to end index in order to start a new section
beg_eq_vals_index = end_eq_vals_index
# Update current value used to determine sub-sections with equal values
cur_val = len(dictionary[sortedKeyList[beg_eq_vals_index]])
else:
if cur_val == -1:
cur_val = len(dictionary[sortedKeyList[end_eq_vals_index]])
# Move end of current section ahead one spot
end_eq_vals_index += 1
# END sort by keys if values are equal
for index in xrange(len(sortedKeyList)):
print("{}: {}".format(sortedKeyList[index], dictionary[sortedKeyList[index]]))
You could test this by adding the reverse=True
optional argument to the "magic line" sorted
call, which results in a sorted
call that looks like:
# Begin magic line
sortedKeyList = sorted(dictionary.keys(), key=lambda s: len(dictionary.get(s)), reverse=True)
# End magic line
Which has an output of:
3: three
7: seven
8: eight
4: four
5: five
9: nine
1: one
2: two
6: six
10: ten
So, you can see that even when we reverse the list, the sub-sections are correctly sorted in ascending key order. Still, this is not the best performance approach so keep that in mind.