Хранение и обновление списков в словарях Python: почему это происходит? - PullRequest
27 голосов
/ 29 ноября 2008

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

// 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 является ключом для словаря, а значение против ключа было бы списком. Затем я могу добавить каждый (х, у) в список. Что-то вроде:

# 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 ()): если он есть, добавить данные, если не создать пустой список в качестве значения словаря, а затем добавить данные в следующем цикле.

Ответы [ 4 ]

72 голосов
/ 29 ноября 2008

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

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. Использовать collection.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 )

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

SetDefault

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

d= {}

Используйте

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

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

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

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

import collections
d = collections.defaultdict(list)

Используйте

d[t].append( c )

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

12 голосов
/ 29 ноября 2008

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

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

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

1 голос
/ 02 декабря 2008

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

#!/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]]
1 голос
/ 29 ноября 2008
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]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...