Я пытаюсь сгруппировать двоичные строки определенных чисел на основе количества единиц в строке.
Это не работает:
s = "0 1 3 7 8 9 11 15"
numbers = map(int, s.split())
binaries = [bin(x)[2:].rjust(4, '0') for x in numbers]
one_groups = dict.fromkeys(range(5), [])
for x in binaries:
one_groups[x.count('1')] += [x]
Ожидаемый словарь one_groups
должен быть
{0: ['0000'],
1: ['0001', '1000'],
2: ['0011', '1001'],
3: ['0111', '1011'],
4: ['1111']}
Но я получаю
{0: ['0000', '0001', '0011', '0111', '1000', '1001', '1011', '1111'],
1: ['0000', '0001', '0011', '0111', '1000', '1001', '1011', '1111'],
2: ['0000', '0001', '0011', '0111', '1000', '1001', '1011', '1111'],
3: ['0000', '0001', '0011', '0111', '1000', '1001', '1011', '1111'],
4: ['0000', '0001', '0011', '0111', '1000', '1001', '1011', '1111']}
Пока единственное, что сработало, это если я использую one_groups[x.count('1')] = one_groups.get(x.count('1')) + [x]
вместоone_groups[x.count('1')] += [x]
Но почему это так? Если я правильно помню, не dict[key]
должен возвращать значение этого словаря, как dict.get(key)
работает? Я видел эту тему Почему dict.get (ключ) вместо dict [ключ]? но он не ответил на мой вопрос для этого конкретного случая, так как я точно знаю, что программа не предназначена для полученияKeyError
Я тоже пытался, one_groups[x.count('1')].append(x)
но это тоже не работает.
python
dictionary
SpectraXCD
источник
источник
get
вернуть,None
если ключ не существует, или любое предоставленное значение по умолчанию, в то время как оператор индекса[]
выдаст ошибку, если ключ не существует.bin(x)[2:].rjust(4, '0')
может быть упрощено до'{:0>4b}'.format(x)
.binaries
, не имеет отношения к вопросу, поэтому вы можете просто указать его значение.Ответы:
Проблема в изменчивости:
one_groups = dict.fromkeys(range(5), [])
- это передает тот же список в качестве значения для всех ключей . Поэтому, если вы измените одно значение, вы измените их все.Это в основном то же самое, что сказать:
Если вы хотите использовать новый список, вам нужно сделать это в цикле - либо в явном
for
цикле, либо в понимании dict:Эта вещь будет «исполняться»
[]
(что равноlist()
) для каждого ключа, создавая значения с различными списками.Почему
get
работает? Потому что вы явно берете текущий список, но создаете+
новый список результатов. И не важно, является ли этоone_groups[x.count('1')] = one_groups.get(x.count('1')) + [x]
или ...one_groups[x.count('1')] = one_groups[x.count('1')] + [x]
важно то, что есть+
.Я знаю, как все говорят
a+=b
, простоa=a+b
, но реализация может быть разной для оптимизации - в случае списков,+=
просто.extend
потому, что мы знаем, что хотим получить наш результат в текущей переменной, поэтому создание нового списка будет пустой тратой памяти.источник
mylist = [[] * 5] * 5
и какmylist = [[] for x in range(5)] * 5
бы это исправить. Просто для быстрого разъяснения, насколько я понял, это происходит из-за переменных, указывающих на адрес памяти этого пустого списка. Означает ли это также, что проблема не возникла бы, если бы я использовал вместо этого примитивы?one_groups[x.count('1')] += [x]
потому что вы не можете добавить список к примитивному типу. Лучшее решение - использовать defaultdict.+
вызывает__add__
и возвращает новый объект, в то время как+=
вызывает__iadd__
и не требуется возвращать новый объектПроблема заключается в использовании
one_groups = dict.fromkeys(range(5), [])
(Это передает тот же список в качестве значения всем ключам. Поэтому, если вы измените одно значение, вы измените их все)
Вы можете использовать это вместо:
one_groups = {i:[] for i in range(5)}
(Эта вещь будет «выполнять» [] (что равно list ()) для каждого ключа, таким образом создавая значения с различными списками.)
источник
Это помощь по
fromkeys
методу dict .Это говорит о том, что fromkeys примет значение, и даже если оно вызывается, оно сначала его оценит, а затем присвоит это значение всем ключам dict.
Списки изменчивы в Python, поэтому он назначит одну и ту же ссылку на пустой список, и одно изменение повлияет на них всех.
Вместо этого используйте defaultdict:
Это примет назначения для несуществующих ключей и значения по умолчанию будут пустыми списками (в этом случае).
источник