0
words = {'apple', 'plum', 'pear', 'peach', 'orange', 'cherry', 'quince'}

d = {}  

for x in sorted(words):  
    if x not in d:  
        d[len(x)]=x  
d[len(x)].append(x)  

print(d)  
AttributeError: 'str' object has no attribute 'append'

The goal of the program is to have a multiple keys, distinguished by word length (i.e., 4, 5, or 6 letters), that store alphabetized values:

{4: 'pear', 'plum' 5: 'apple', 'peach' 6: 'cherry', 'orange', 'quince'}

I am having issues adding items to a key. What I am currently getting as my output is (without the append line):

{4: 'plum', 5: 'peach', 6: 'quince'}

so it seems to be erasing the previous loops entry. The update and append commands are coming back with errors.

Prune
  • 76,765
  • 14
  • 60
  • 81
Kyle
  • 1

2 Answers2

2

You can use collections.defaultdict to create a dictionary that stores each item based on their length:

from collections import defaultdict
d = defaultdict(list)
words = {'apple', 'plum', 'pear', 'peach', 'orange', 'cherry', 'quince'} 
for word in words:
   d[len(word)].append(word)

final_data = {a:sorted(b) for a, b in d.items()}

Output:

{4: ['pear', 'plum'], 5: ['apple', 'peach'], 6: ['cherry', 'orange', 'quince']}

Also, itertools.groupby can be used for a shorter solution:

import itertools
words = {'apple', 'plum', 'pear', 'peach', 'orange', 'cherry', 'quince'} 
new_words = {a:sorted(list(b)) for a, b in itertools.groupby(sorted(words, key=len), key=len)}

Output:

{4: ['pear', 'plum'], 5: ['apple', 'peach'], 6: ['cherry', 'orange', 'quince']}
Ajax1234
  • 69,937
  • 8
  • 61
  • 102
  • 1
    Excellent use of `groupby`. I'm not a fan of the new dictionary and new sublists created for `final_data` when sorting in place would do as in `for sublist in d.values(): sublist.sort()`. Sorting beforehand would also work as in `for word in sorted(words):`. (Of course it's all preference. One nice thing about the dict comprehension is that you no longer have a `defaultdict`.) – Steven Rumbalski Jan 23 '18 at 20:10
  • @StevenRumbalski I too prefer `groupby` :) It seems, however, that some users on SO prefer `defaultdict` so I thought it best to provide a solution utilizing both. – Ajax1234 Jan 23 '18 at 20:17
1

You can't append to a string; you have to make your dict values lists from the beginning. You also have two checks, not one:

  • Does the dict have any words of the current length?
  • Is the given word already in the list?

Try this:

size = len(x)
if size not in d:  
    d[size] = [x]
else:
    d[size].append(x)
Prune
  • 76,765
  • 14
  • 60
  • 81