2

I am trying to iterate over a dictionary (inside another dictionary specifically, but I don't think that part matters), and I'm unable to get the for loop to iterate over the values in the order that they were placed in. I would like to be able to take the first value of each dictionary. I thought that after python 3.6, dictionaries kept their order (here), but these wont stay in order.

This is what my dictionary looks like:

count_dict = {'dessert': Counter({'cake': 1}), 'vegetable': Counter({'carrots': 1, 'beet': 1}), 'grain': Counter({'wheat': 3, 'rice': 2, 'zantham': 1}), 'meat': Counter({'chicken': 2, 'pork': 1})}

This is my code that tried:

for it in count_dict:
        for food in count_dict[it]:
            out_dict[it] = food
return(out_dict)

I get:

{'dessert': 'cake', 'vegetable': 'beet', 'grain': 'rice', 'meat': 'chicken'}

but need to get the first value from each dictionary:

{'dessert': 'cake', 'vegetable': 'carrots', 'grain': 'wheat', 'meat': 'chicken'}

I looked for ever for an answer on Stack but couldn't find an answer. (sorry if the answers obvious, I'm kinda new to Python)

magic.mrr
  • 25
  • 4
  • Notice that your actual output and expected output have an identical ordering by keys. That is what is meant by the ordering being retained: the keys keep the same order. Clearly, in this case, the dictionaries that counter uses do not keep their order. – Kraigolas May 26 '21 at 04:27
  • `beet` is not a first value, but you said you want first value from. – nobleknight May 26 '21 at 04:48

2 Answers2

1

Dictionaries (after python 3.6) maintain their insertion order (order in which keys and values are inserted), not the sorted order.


I did get an answer.

from collections import Counter

count_dict = {'dessert': Counter({'cake': 1}), 'vegetable': Counter({'carrots': 1, 'beet': 1}), 'grain': Counter({'wheat': 3, 'rice': 2, 'zantham': 1}), 'meat': Counter({'chicken': 2, 'pork': 1})}

new_dict = {}

for a, b in count_dict.items():
    new_dict[a] = sorted(b, key=lambda x: (-b[x], x))[0]

print(new_dict)

This will sort inner dictionary first by the values then alphabetically by keys.

sorted(b, key=lambda x: (-b[x], x))

Sample Run 1 (sorting alphabetically, because values are same.)

b = {'carrots': 1, 'beet': 1}
sorted(b, key=lambda x: (-b[x], x))

Output

['beet', 'carrots']

Sample Run 2 (sorting by value an the alphabetically.)

b = {'wheat': 3, 'rice': 2, 'zantham': 1}
sorted(b, key=lambda x: (-b[x], x))

Output

['wheat', 'rice', 'zantham']
Dharman
  • 30,962
  • 25
  • 85
  • 135
nobleknight
  • 755
  • 6
  • 15
  • thanks, I had this in the back of my mind, but was not sure how to do it. Sorry to ask for more, but how does the (-b[x]), x) section work in the lambda function? – magic.mrr May 26 '21 at 05:06
  • 1
    `b[x]` gives value for key `x`. `sorted` will sort it by ascending order of values. When we change it to `-b[x]`, maximum value will be minimum. So we will get it reverse order by values. You can say that why don't we used `reverse` parameter, but we also want it to sorted by alphabetically by keys. If values for two keys are same, then `sorted` will check key `x` and sort it according to key `x`. – nobleknight May 26 '21 at 05:15
0

If you strictly want to return the first key value only, regardless of alphabetical key order or numerical value order, you could simply do the following:

from collections import Counter

count_dict = {'dessert': Counter({'cake': 1}), 'vegetable': Counter({'carrots': 1, 'beet': 1}), 'grain': Counter({'wheat': 3, 'rice': 2, 'zantham': 1}), 'meat': Counter({'chicken': 2, 'pork': 1})}
out_dict = {}

for it in count_dict:
        for food in count_dict[it]:
            out_dict[it] = food
            break  # Break out the loop so that you only iterate over the first key in dictionary
print(out_dict)
Omar AlSuwaidi
  • 1,187
  • 2
  • 6
  • 26