Хранение и обновление списков в словарях Python: почему это происходит?

У меня есть список данных, который выглядит следующим образом:

// timestep,x_position,y_position
0,4,7
0,2,7
0,9,5
0,6,7
1,2,5
1,4,7
1,9,0
1,6,8

... и я хочу, чтобы это выглядело так:

0, (4,7), (2,7), (9,5), (6,7)
1, (2,5), (4,7), (9,0), (6.8)

Мой план состоял в том, чтобы использовать словарь, где значение t является ключом для словаря, а значение для ключа будет списком. Затем я мог бы добавить каждый (x, y) в список. Что-то типа:

# where t = 0, c = (4,7), d = {}

# code 1
d[t].append(c)

Теперь это приводит к сбою IDLE. Однако, если я это сделаю:

# code 2
d[t] = []
d[t].append(c)

... это работает.

Возникает вопрос: почему код 2 работает, а код 1 - нет?

PS Любые улучшения в том, что я планирую сделать, будут очень интересны !! Я думаю, мне придется проверять словарь в каждом цикле через ввод, чтобы увидеть, существует ли уже ключ словаря, я думаю, используя что-то вроде max (d.keys ()): если он есть, добавить данные, если не создать пустой список в качестве значения словаря, а затем добавить данные в следующем цикле.

"Не работает холостой ход?" Не очень содержательно. Укажите фактическое сообщение об ошибке.

S.Lott 29.11.2008 16:49
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
27
1
93 338
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Ответ принят как подходящий

Давайте посмотрим на

d[t].append(c)

В чем ценность d[t]? Попробуй это.

d = {}
t = 0
d[t]

Что вы получаете? Ой. В d нет ничего, что имеет ключ t.

А теперь попробуйте это.

d[t] = []
d[t]

Ах. Сейчас есть что-то в d с ключом от t.

Вы можете сделать несколько вещей.

  1. Используйте пример 2.
  2. Используйте setdefault. d.setdefault(t,[]).append(c).
  3. Используйте collections.defaultdict. Вы бы использовали defaultdict(list) вместо простого словаря {}.

Изменить 1. Оптимизация

Учитывая входные строки из файла в приведенной выше форме: ts, x, y, процесс группировки не требуется. Нет причин переходить от простого списка (ts, x, y) к более сложному список (ts, (x, y), (x, y), (x, y), ...). Исходный список можно обработать точно так, как он был получен.

d= collections.defaultdict(list)
for ts, x, y in someFileOrListOrQueryOrWhatever:
    d[ts].append( (x,y) )

Изменить 2. Ответить на вопрос

"при инициализации словаря вам нужно сообщить словарю, как будет выглядеть структура данных ключ-значение?"

Я не уверен, что означает вопрос. Поскольку все словари являются структуры ключ-значение, вопрос не очень ясен. Итак, я рассмотрю три альтернативы, которые могут ответить на вопрос.

Пример 2.

Инициализация

d= {}

Использовать

if t not in d:
    d[t] = list()
d[t].append( c )

Каждое значение словаря должно быть инициализировано некоторой полезной структурой. В этом случае мы проверяем наличие ключа; когда ключ отсутствует, мы создаем ключ и назначаем пустой список.

Установить по умолчанию

Инициализация

d= {}

Использовать

d.setdefault(t,list()).append( c )

В этом случае мы используем метод setdefault, чтобы либо получить значение, связанное с ключом, либо создать новое значение, связанное с отсутствующим ключом.

dict по умолчанию

Инициализация

import collections
d = collections.defaultdict(list)

Использовать

d[t].append( c )

defaultdict использует функцию инициализации недостающих клавиш. В этом случае мы предоставляем функцию list, чтобы создать новый пустой список для отсутствующего ключа.

Значит ли это, что при инициализации словаря вам нужно сообщить словарю, как будет выглядеть структура данных «ключ-значение»? Извините, я исхожу из фона Perl, который я не использовал в гневе годами, так что, возможно, я продолжаю работать с разбитыми воспоминаниями, поскольку был уверен, что вы можете сделать это анонимно.

user41121 29.11.2008 17:02
dict=[]  //it's not a dict, it's a list, the dictionary is dict = {}
elem=[1,2,3]
dict.append(elem)

вы можете получить доступ к отдельному элементу таким образом:

print dict[0] // 0 is the index

вывод будет:

[1, 2, 3]

Python достаточно сбивает с толку своей нерегулярной скобкой, чтобы добавить к ней имя функции (dict () должна возвращать пустой dict), похожее на структуру данных, и сделать ее переменной.

jibay 23.04.2012 19:42

Я думаю, вы хотите использовать setdefault. Это немного странно в использовании, но делает именно то, что вам нужно.

d.setdefault(t, []).append(c)

Метод .setdefault вернет элемент (в нашем случае список), связанный с ключом dict t, если этот ключ существует. В противном случае он привяжет пустой список к ключу t и вернет его. Так или иначе, будет список, в который метод .append может затем добавить кортеж c.

Если ваши данные еще не отсортированы по желаемым критериям, вот код, который может помочь сгруппировать данные:

#!/usr/bin/env python
"""
$ cat data_shuffled.txt
0,2,7
1,4,7
0,4,7
1,9,0
1,2,5
0,6,7
1,6,8
0,9,5
"""
from itertools   import groupby
from operator    import itemgetter

# load the data and make sure it is sorted by the first column
sortby_key = itemgetter(0)
data = sorted((map(int, line.split(',')) for line in open('data_shuffled.txt')),
              key=sortby_key)

# group by the first column
grouped_data = []
for key, group in groupby(data, key=sortby_key):
    assert key == len(grouped_data) # assume the first column is 0,1, ...
    grouped_data.append([trio[1:] for trio in group])

# print the data
for i, pairs in enumerate(grouped_data):
    print i, pairs

Выход:

0 [[2, 7], [4, 7], [6, 7], [9, 5]]
1 [[4, 7], [9, 0], [2, 5], [6, 8]]

Другие вопросы по теме