Here's the question I'm trying to solve:
Given a dictionary, whose keys are binary strings, and values are numbers, for example:
result = {'000': 25, '010': 34, '100':22, '101':35}
, my goal is to first sort the keys with the same number of 'bit flips', then add up the associated values, and return them in an ascending order based on the number of flips. For example, in this case, the desired output could be[25,22,69]
(0,1,and 2 flips).
I have the first part of my code, which is to transform the strings into the number of bit flips:
def count_flip(string):
return len([x for x in range(1, len(string)) if string[x] != string[x-1]])
I'm stuck on the second part, which is to return the values with the order specified, given a dictionary input such as result
. My thought is to loop through all the keys in the input dictionary, but I really don't know how can I absorb the strings (keys) with the same number of flips, applying count_flip(string)
?
CodePudding user response:
collections.Counter
should help.
from collections import Counter
flip_counts = Counter()
for binary_string, value in result.items():
flip_counts[count_flip(binary_string)] = value
output = [v for _, v in sorted(flip_counts.items())]
CodePudding user response:
You can use collections.defaultdict
for this:
counts = defaultdict(int)
for k, v in result.items():
counts[count_flip(k)] = v
Since sorting of tuples is lexicographic, you can do
counts = sorted(counts.items())
Extracting the second element can be done with a comprehension:
[c[1] for c in counts]
or with a transpose:
list(zip(*counts))[1]
As of python 3.6, dictionaries are automatically sorted by insertion order, so you can do this simpler by pre-populating the keys up-front:
counts = dict.fromkeys(sorted(set(map(count_flip, result))), 0)
for k, v in result.items():
counts[count_flip(k)] = v
This way, the result is just
list(counts.values())
With older versions of python, you can use collections.OrderedDict
for the same effect.