4

I would like to iterate over a dictionary, and append each key (letter) repeated by the number of times of its value (frequency) to a new list.

For example: input: {'A':1, 'B':2}. Expected output: ['A', 'B', 'B']

What I'm doing is not working. What do I write in my function to do this?

def get_freq_dict():
    freq_dict = {'J' : 1, 'K' : 1, 'Q' : 1, 'X' : 1, 'Z' : 1,\
                'B' : 2, 'C' : 2, 'F' : 2, 'H' : 2, 'M' : 2, 'P' : 2,\
                'V' : 2, 'W' : 2, 'Y' : 2, '' : 2,\
                'G' : 3, 'D' : 4, 'L' : 4, 'S' : 4, 'U' : 4,\
                'N' : 6, 'R' : 6, 'T' : 6, 'O' : 8, 'A' : 9, 'I' : 9,\
                'E' : 12}
    return freq_dict


def bag_of_letters(freq_dict):
    freq_lst = [] 
    for key, value in freq_dict.items():
        for range in(value):
            freq_lst.append(value)
    return freq_lst


def main():

    freq_dict = get_freq_dict()
    freq_lst = bag_of_letters(freq_dict)

    print(freq_dict, freq_lst)
main()
jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
Tim
  • 51
  • 1
  • 6
  • `for range in(value):` seems suspicious, maybe rethink that line. – jonrsharpe Feb 21 '19 at 08:14
  • 1
    Please also add in your question what exactly is not working. Do you get an exception? What is your result? – Tobias Brösamle Feb 21 '19 at 08:16
  • Does this answer your question? [Convert dictionary into list with length based on values](https://stackoverflow.com/questions/39987708/convert-dictionary-into-list-with-length-based-on-values) – Georgy Aug 06 '20 at 14:10

5 Answers5

4

The culprit:

for range in(value):
    freq_lst.append(value)

The rescuer:

for i in range(value):
     freq_lst.append(key)

Hence:

def get_freq_dict():
    freq_dict = {'J' : 1, 'K' : 1, 'Q' : 1, 'X' : 1, 'Z' : 1,\
                'B' : 2, 'C' : 2, 'F' : 2, 'H' : 2, 'M' : 2, 'P' : 2,\
                'V' : 2, 'W' : 2, 'Y' : 2, '' : 2,\
                'G' : 3, 'D' : 4, 'L' : 4, 'S' : 4, 'U' : 4,\
                'N' : 6, 'R' : 6, 'T' : 6, 'O' : 8, 'A' : 9, 'I' : 9,\
                'E' : 12}
    return freq_dict


def bag_of_letters(freq_dict):
    freq_lst = []
    for key, value in freq_dict.items():
       # print(key, value)
        for i in range(value):
            freq_lst.append(key)
    return freq_lst


def main():

    freq_dict = get_freq_dict()
    freq_lst = bag_of_letters(freq_dict)

    print(freq_lst)
main()

OUTPUT:

['J', 'K', 'Q', 'X', 'Z', 'B', 'B', 'C', 'C', 'F', 'F', 'H', 'H', 'M', 'M', 'P', 'P', 'V', 'V', 'W', 'W', 'Y', 'Y', '', '', 'G', 'G', 'G', 'D', 'D', 'D', 'D', 'L', 'L', 'L', 'L', 'S', 'S', 'S', 'S', 'U', 'U', 'U', 'U', 'N', 'N', 'N', 'N', 'N', 'N', 'R', 'R', 'R', 'R', 'R', 'R', 'T', 'T', 'T', 'T', 'T', 'T', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'I', 'I', 'I', 'I', 'I', 'I', 'I', 'I', 'I', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E']

OR

if you want them nicely paired:

 for i in range(value):
     freq_lst.append([key]*value)

OP: However I'm still having trouble with the printed output. It gives me what I'm looking for but also the original dictionary on top

Ans: Because you're printing both the dict and the list:

print(freq_dict, freq_lst)

Just print the list instead:

print(freq_lst)

EDIT 2:

Another nicer way of grouping the similar elements together, using groupby():

Append the key only:

 for i in range(0, value):
      freq_lst.append(key)

and then:

 print([list(j) for i, j in groupby(freq_lst)])

OUTPUT:

[['J'], ['K'], ['Q'], ['X'], ['Z'], ['B', 'B'], ['C', 'C'], ['F', 'F'], ['H', 'H'], ['M', 'M'], 
 ['P', 'P'], ['V', 'V'], ['W', 'W'], ['Y', 'Y'], ['', ''], ['G', 'G', 'G'], 
 ['D', 'D', 'D', 'D'], ['L', 'L', 'L', 'L'], ['S', 'S', 'S', 'S'], ['U', 'U', 'U', 'U'], 
 ['N', 'N', 'N', 'N', 'N', 'N'], ['R', 'R', 'R', 'R', 'R', 'R'], 
 ['T', 'T', 'T', 'T', 'T', 'T'], ['O', 'O', 'O', 'O', 'O', 'O', 'O', 'O'], 
 ['A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A'], 
 ['I', 'I', 'I', 'I', 'I', 'I', 'I', 'I', 'I'], 
 ['E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E']]
DirtyBit
  • 16,613
  • 4
  • 34
  • 55
0

You should iterate through a range instead, and append key rather than value:

for key, value in freq_dict.items():
    for _ in range(value):
        freq_lst.append(key)

Alternatively, you can use a list comprehension:

def bag_of_letters(freq_dict):
    return [i for k, v in freq_dict.items() for i in [k] * v]
blhsing
  • 91,368
  • 6
  • 71
  • 106
  • 1
    `freq_lst.extend([key]*value)` ? – Chris_Rands Feb 21 '19 at 08:19
  • Thank you that makes more sense. However I'm still having trouble with the printed output. It gives me what I'm looking for but also the original dictionary on top. ex - {'J': 1, 'K': 1, 'Q': 1,'.... ['J', 'K', 'Q', …..]} where all i'm looking for is ['J', 'K', 'Q', …..]} – Tim Feb 21 '19 at 08:20
  • @Tim You can `print(freq_lst)` instead of `print(freq_dict, freq_lst)`. – blhsing Feb 21 '19 at 08:24
0

Here you are

freq_dict = {'J' : 1, 'K' : 1, 'Q' : 1, 'X' : 1, 'Z' : 1,\
            'B' : 2, 'C' : 2, 'F' : 2, 'H' : 2, 'M' : 2, 'P' : 2,\
            'V' : 2, 'W' : 2, 'Y' : 2, '' : 2,\
            'G' : 3, 'D' : 4, 'L' : 4, 'S' : 4, 'U' : 4,\
            'N' : 6, 'R' : 6, 'T' : 6, 'O' : 8, 'A' : 9, 'I' : 9,\
            'E' : 12}


def bag_of_letters():
    freq_lst = []

    for key in freq_dict:
        for i in range(0, freq_dict[key]):
            freq_lst.append(key)

    return freq_lst


def main():
    freq_lst = bag_of_letters()
    print(freq_lst)


main()

result ['J', 'K', 'Q', 'X', 'Z', 'B', 'B', 'C', 'C', 'F', 'F', 'H', 'H', 'M', 'M', 'P', 'P', 'V', 'V', 'W', 'W', ecc]

Hele
  • 189
  • 1
  • 12
0

You could harness fact that

If items(), keys(), values(), iteritems(), iterkeys(), and itervalues() are called with no intervening modifications to the dictionary, the lists will directly correspond.

as shown in this topic, therefore you might just do:

import itertools
x = {'A':1, 'B':2}
out = list(map(lambda x,y: [x]*y, x.keys(), x.values()))
print(out) #[['A'], ['B', 'B']]
out = list(itertools.chain.from_iterable(out))
print(out) #['A', 'B', 'B']

I used itertools to flatten list, if you do not wish to import itertools you might do:

out = sum(out,[])

instead of

out = list(itertools.chain.from_iterable(out))
Daweo
  • 31,313
  • 3
  • 12
  • 25
0

You can easily do it with Counter:

from collections import Counter

d = {'C': 3, 'B': 2, 'A': 1}
c = Counter(d)
list(c.elements())
# ['C', 'C', 'C', 'B', 'B', 'A']
Mykola Zotko
  • 15,583
  • 3
  • 71
  • 73