2016-05-29 3 views
0

Как изменить список, как это:изменить список в словаре

[[0, 'Ealing Broadway', 103.89], 
[0, 'Notting Hill Gate', 103.89], 
[0, 'Mile End', 103.89], 
[1, 'Ealing Broadway', 59.089999999999996], 
[2, 'Notting Hill Gate', 40.279999999999994], 
[3, 'Mile End', 68.86999999999999]] 

к словарю, как

{0:{'length':103.89,'interchange':['Ealing Broadway','Notting Hill Gate','Mile End']}, 
1:{'length':59.089999999999996,'interchange':['Ealing Broadway']}, 
2:{'length':40.279999999999994,'interchange':['Notting Hill Gate']}, 
3:{'length':68.86999999999999,'interchange':['Mile End']}} 

Благодарности

I am trying to start with: 

d2 = defaultdict(list) 
for k, v in all_info: 
    d2[k].append(v) 

with_length=dict((k,list(v)) for k,v in d2.iteritems()) 
with_length 

, но он не работает, я я боюсь, с чего начать.

+2

Всегда ли одно значение первого элемента подсети указывает одно значение в последнем элементе в подсписке? –

+0

Я заинтригован относительно того, к чему относятся эти «длины». Длина платформы? –

+0

0,1,2,3 можно понимать как маршрут. Название станций - это обмен в этом маршруте. Конечным значением является длина маршрута. –

ответ

0

Аналогичный ответ майора, но с использованием groupby. Нет ложных поисков, но может потребоваться сортировка заранее.

from itertools import groupby 

lst = [[0, 'Ealing Broadway', 103.89], 
    [0, 'Notting Hill Gate', 103.89], 
    [0, 'Mile End', 103.89], 
    [1, 'Ealing Broadway', 59.089999999999996], 
    [2, 'Notting Hill Gate', 40.279999999999994], 
    [3, 'Mile End', 68.86999999999999]] 

new_list = [] 
for key, group in groupby(lst, lambda x: x[0]): 
    new_list.append(list(group)) 

main_dict = {} 
for item in new_list: 
    main_dict[item[0][0]] = {'length': item[0][2], 'interchange': [stn[1] for stn in item]} 
0

Вот конкретный пример того, как вы могли бы сделать, что:

l = [[0, 'Ealing Broadway', 103.89], 
    [0, 'Notting Hill Gate', 103.89], 
    [0, 'Mile End', 103.89], 
    [1, 'Ealing Broadway', 59.089999999999996], 
    [2, 'Notting Hill Gate', 40.279999999999994], 
    [3, 'Mile End', 68.86999999999999]] 

d = {} 

for pair in l: 
    if pair[0] not in d.keys(): 
     d[pair[0]] = { 'interchange': [] } 

    d[pair[0]]['length'] = pair[2] 
    d[pair[0]]['interchange'].append(pair[1]) 

Это предполагает, что вы хотите перезаписать d['length'] при добавлении элемента в d[0].

0
b = {} 
for i in a: 
    if b.has_key(i[0]): 
     b[i[0]]['interchange'].append(i[1]) 
    else: 
     b[i[0]] = {'length': i[2], 'interchange': [i[1]]} 
+0

Это почти то же самое, что и второе редактирование моего ответа. – Majora320

+0

@ Majora320 Это также не полный ответ на тест. Я не уверен, как это заняло самое высокое место. Я решил ответить не потому, что я думаю, что у меня есть лучшее, но я бы критиковал свой ответ, если это не устраивает проблему. – roganjosh

0

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

import pprint 

if __name__ == '__main__': 
    rows = [ 
     [0, 'Ealing Broadway', 103.89], 
     [0, 'Notting Hill Gate', 103.89], 
     [0, 'Mile End', 103.89], 
     [1, 'Ealing Broadway', 59.089999999999996], 
     [2, 'Notting Hill Gate', 40.279999999999994], 
     [3, 'Mile End', 68.86999999999999]] 

    print('First Pass') 
    d = {} 
    for key, interchange, length in rows: 
     inner_dict = d.setdefault((key, length), {}) 
     interchanges = inner_dict.setdefault('interchange', []) 
     interchanges.append(interchange) 

    pprint.pprint(d) 

    print('=' * 72) 
    print('Second Pass') 
    d2 = {} 
    for (key, length), v in d.items(): 
     v['length'] = length 
     d2[key] = v 

    pprint.pprint(d2) 

Выход

First Pass 
{(0, 103.89): {'interchange': ['Ealing Broadway', 
           'Notting Hill Gate', 
           'Mile End']}, 
(1, 59.089999999999996): {'interchange': ['Ealing Broadway']}, 
(2, 40.279999999999994): {'interchange': ['Notting Hill Gate']}, 
(3, 68.86999999999999): {'interchange': ['Mile End']}} 
======================================================================== 
Second Pass 
{0: {'interchange': ['Ealing Broadway', 'Notting Hill Gate', 'Mile End'], 
    'length': 103.89}, 
1: {'interchange': ['Ealing Broadway'], 'length': 59.089999999999996}, 
2: {'interchange': ['Notting Hill Gate'], 'length': 40.279999999999994}, 
3: {'interchange': ['Mile End'], 'length': 68.86999999999999}} 

Обсуждения

  • В первом проходе, я использую первые и последние столбцы в качестве ключа к словарю. Значение этого словаря - еще один словарь (inner_dict)
  • Во втором проходе я настраиваю ключи и значения в окончательную форму.
  • Это решение не может быть наиболее эффективным и элегантным, но я надеюсь, что это легко понять
0

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

Я уверен, что если вы хотите обрабатывать большое количество данных быстро - панды это ваш инструмент ...

import pandas as pd 

data = [[0, 'Ealing Broadway', 103.89], 
     [0, 'Notting Hill Gate', 103.89], 
     [0, 'Mile End', 103.89], 
     [1, 'Ealing Broadway', 59.089999999999996], 
     [2, 'Notting Hill Gate', 40.279999999999994], 
     [3, 'Mile End', 68.86999999999999] 
     ] 

# create pandas DF 
df = pd.DataFrame(data, columns=['route','interchange','length']) 

Оригинал DF: группа

In [235]: df 
Out[235]: 
    route  interchange length 
0  0 Ealing Broadway 103.89 
1  0 Notting Hill Gate 103.89 
2  0   Mile End 103.89 
3  1 Ealing Broadway 59.09 
4  2 Notting Hill Gate 40.28 
5  3   Mile End 68.87 

ДАВАЙТЕ наши данные :

In [239]: df.groupby(['route','length'])['interchange'].apply(lambda x: x.tolist()).reset_index() 
Out[239]: 
    route length          interchange 
0  0 103.89 [Ealing Broadway, Notting Hill Gate, Mile End] 
1  1 59.09        [Ealing Broadway] 
2  2 40.28        [Notting Hill Gate] 
3  3 68.87          [Mile End] 

мы также можем преобразовать его в список dicts:

In [240]: df.groupby(['route','length'])['interchange'].apply(lambda x: x.tolist()).reset_index().to_dict('record') 
Out[240]: 
[{'interchange': ['Ealing Broadway', 'Notting Hill Gate', 'Mile End'], 
    'length': 103.89, 
    'route': 0}, 
{'interchange': ['Ealing Broadway'], 
    'length': 59.089999999999996, 
    'route': 1}, 
{'interchange': ['Notting Hill Gate'], 
    'length': 40.279999999999994, 
    'route': 2}, 
{'interchange': ['Mile End'], 'length': 68.86999999999999, 'route': 3}] 

Сроки для 600.000 строк кадра данных на моем домашнем ноутбуке:

Установка:

In [245]: a = pd.concat([df] * 10**5) 

Форма объединенного a DF:

In [246]: a.shape 
Out[246]: (600000, 3) 

timeit:

In [251]: %timeit a.groupby(['route','length'])['interchange'].apply(lambda x: x.tolist()).reset_index() 
10 loops, best of 3: 130 ms per loop 

Не-Векторизованный подход (для петли/понимание списка/и т. д.):

In [262]: %paste 
def roganjosh(lst): 
    new_list = [] 
    for key, group in groupby(lst, lambda x: x[0]): 
     new_list.append(list(group)) 

    main_dict = {} 
    for item in new_list: 
     main_dict[item[0][0]] = {'length': item[0][2], 'interchange': [stn[1] for stn in item]} 

    return main_dict 
## -- End pasted text -- 

In [263]: lst = a.values.tolist() 

In [264]: len(lst) 
Out[264]: 600000 

In [265]: %timeit roganjosh(lst) 
1 loop, best of 3: 650 ms per loop 
+0

Вы потеряли 'длину'? – roganjosh

+1

@roganjosh, вы правы, спасибо! Я исправил свой ответ – MaxU

+0

:) Я думаю, что пришло время для меня поразить 'timeit' heh – roganjosh