1

My binary_list is a list of strings of "000", "001", "010",....

I am trying to add into a dictionary the number of 1's in each string of bits. he dictionary will be created with the size of n for each number of 1's that appear in the string

I can't seem to append the string of bits to a list and then add it to the dictionary. When I run the code I get:

input: sortbits(3)

000
001
010
011
100
101
110
111
{0: [], 1: [], 2: []}

correct output is:

000
001
010
011
100
101
110
111
{0: [000], 1: [001, 010, 100], 2: [011,101, 110], 3: [111]}

my code:

def sortbit(n):
    max_num = 2**n
    binary_list = []
    for x in range(0,max_num):
        stringy = []
        for a in range(n):
            stringy.append(str(x%2))
            x //= 2
        print ''.join(reversed(stringy))

        stringy_list = ''.join(reversed(stringy))
        binary_list.append(stringy_list)

    count_dict = dict.fromkeys(range(0,n+1))

    for element in binary_list:
        count = 0
        value_list = []
        for character in element:
            if character == '1':
                count += 1
        for y in count_dict:
            if y == str(count):
                value_list.append(element)
            count_dict[y] = value_list 

    print count_dict
Liondancer
  • 15,721
  • 51
  • 149
  • 255

5 Answers5

5
>>>strings=["000","001","010","011","100","101","110","111"]
>>>d={}
>>>for s in strings:
...     count = s.count("1")
...     if count not in d:
...             d[count]=[]
...     d[count].append(s)

>>>d
{0: ['000'], 1: ['001', '010', '100'], 2: ['011', '101', '110'], 3: ['111']}
Ishaan
  • 886
  • 6
  • 12
3

collections.defaultdict would be more appropriate here:

>>> from collections import defaultdict
>>> dic = defaultdict(list)
for i in xrange(8):
    bi = format(i, '03b')
    dic[bi.count('1')].append(bi)
...     
>>> dic
defaultdict(<type 'list'>, {
0: ['000'],
1: ['001', '010', '100'],
2: ['011', '101', '110'],
3: ['111']})
Ashwini Chaudhary
  • 244,495
  • 58
  • 464
  • 504
2

This works:

>>> lst = ['000', '001', '010', '011', '100', '101', '110', '111']
>>> dct = {x:[] for x in xrange(max(map(len, lst))+1)}
>>> for item in lst:
...     dct[item.count('1')].append(item)
...
>>> dct
{0: ['000'], 1: ['001', '010', '100'], 2: ['011', '101', '110'], 3: ['111']}
>>>

All of this should be pretty straightforward except for maybe this part: max(map(len, lst)). What this does is calculate the greatest length of the items in lst. In this case, the greatest length is 3. If I were to add another item to lst that had 4 characters (e.g. "1010"), the greatest length would be 4.

You need this to determine how many keys to place in dct. The number of keys you need will always be the greatest length of the items in lst + 1.

  • Normal `dict` has a `setdefault` method, that can be used here instead of initializing a dict with empty lists. – Ashwini Chaudhary Oct 08 '13 at 17:29
  • @iCodez This is straightforward but I'm not sure why I am getting the error `Traceback (most recent call last): File "", line 1, in File "facebook_prob.py", line 23, in sortbit count_dict[element.count('1')].append(element) AttributeError: 'NoneType' object has no attribute 'append' ` – Liondancer Oct 09 '13 at 05:14
  • I don't know either. Perhaps you have `element` defined somewhere else. The code I gave was tested and works. –  Oct 09 '13 at 13:33
2
from collections import defaultdict
def sortbit(n):
    d = defaultdict(list)
    max_val = 2**n
    for x in range(0,max_val):
       d[bin(x).count("1")].append("{0:0{1}b}".format(x,n))
    return d

I think at least, this will make your binary values automagically n wide

>>> sortbit(3)
defaultdict(<type 'list'>, {0: ['000'], 1: ['001', '010', '100'], 2: ['011', '10
1', '110'], 3: ['111']})
>>> sortbit(4)
defaultdict(<type 'list'>, {0: ['0000'], 1: ['0001', '0010', '0100', '1000'], 2:
 ['0011', '0101', '0110', '1001', '1010', '1100'], 3: ['0111', '1011', '1101', '
1110'], 4: ['1111']})
Joran Beasley
  • 110,522
  • 12
  • 160
  • 179
2

Edit: Corrected dict.getkeys error in generating dictionary

When you create your dictionary, you can save time by creating lists attached to each key in the same line. This should fix your problem:

count_dict = {x:[] for x in range(0,n+1)}

You could also clean up the bottom portion in this way:

for element in binary_list:
    count_dict[element.count('1')].append(element)

Hope this helps!

  • This will generate incorrect results as `dict.fromkeys` will give each key the *same list* as its value. eg: `a = dict.fromkeys([1, 2], []); a[1].append('item')` gives you `a` as: `{1: ['item'], 2: ['item']}` – Jon Clements Oct 08 '13 at 17:47
  • 1
    -1 Why this answer is incorrect: [python: Why listA.append('a') affects listB?](http://stackoverflow.com/questions/19165542/python-why-lista-appenda-affects-listb) – Ashwini Chaudhary Oct 08 '13 at 18:02
  • 1
    duly noted. I had never used `dict.fromkeys` before. Didn't realize it would give every key the same list. – Chris Nemarich Oct 09 '13 at 00:18