Tim
Tim

Reputation: 51

Iterate through Python dictionary and special append to new list?

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()

Upvotes: 4

Views: 6378

Answers (5)

Mykola Zotko
Mykola Zotko

Reputation: 17824

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']

Upvotes: 0

Daweo
Daweo

Reputation: 36430

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))

Upvotes: 0

DirtyBit
DirtyBit

Reputation: 16772

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']]

Upvotes: 4

blhsing
blhsing

Reputation: 106543

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]

Upvotes: 0

Hele
Hele

Reputation: 405

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]

Upvotes: 0

Related Questions