2012-06-17 3 views
2

У меня есть список списков, который выглядит как этотPython, Как эффективно сделать вложенный словарь из списка списков

[['ip1',404], 
['ip1',200], 
['ip1',200], 
['ip2',200], 
['ip2',200], 
['ip2',504]] 

мне нужно сделать словарь, который имеет отсчеты кодов состояния по IP-адресу ,

results = {'ip1':{404:1,200:2},'ip2':{200:2,504:1}} 
+2

При предоставлении образец кода, пожалуйста, по крайней мере, проверить, что это синтаксически правильным. –

+0

Он по-прежнему недействителен. –

+0

Я исправил это, http://sscce.org/#co – jamylak

ответ

9

Инструменты в коллекции расправиться этой проблемы:

>>> from collections import defaultdict, Counter 
>>> d = defaultdict(Counter) 
>>> for ip, code in [['ip1',404], ['ip1',200], ['ip1',200], 
        ['ip2',200], ['ip2',200], ['ip2',504]]: 
     d[ip][code] += 1 

>>> dict(d) 
{'ip2': Counter({200: 2, 504: 1}), 'ip1': Counter({200: 2, 404: 1})} 
+1

+1 для включения 'from collections import defaultdict' –

+0

Теперь это часть моего инструментария ... никогда не знала, что это было! – Tampa

+0

Нет необходимости преобразовывать результат в 'dict' -' defaultdict'/'Counter' - это подклассы из' dict' и могут использоваться напрямую. – astynax

0
>>> l 
[['ip1', 404], 
['ip1', 200], 
['ip1', 200], 
['ip2', 200], 
['ip2', 200], 
['ip2', 504]] 

>>> {ip: {code: l.count([ip, code]) 
... for code in (p[1] for p in l if p[0]==ip)} 
...   for ip in (p[0] for p in l)} 
{'ip1': {200: 2, 404: 1}, 'ip2': {200: 2, 504: 1}} 
+0

Это не очень эффективно в вычислительном смысле. –

3
>>> from collections import defaultdict 
>>> d = defaultdict(lambda: defaultdict(int)) 
>>> ips = [['ip1',404],['ip1',200],['ip1',200],['ip2',200],['ip2',200],['ip2',504]] 
>>> for ip,num in ips: 
     d[ip][num] += 1 

>>> d 
defaultdict(<function <lambda> at 0x00000000035D6648>, {'ip2': defaultdict(<class 'int'>, {200: 2, 504: 1}), 'ip1': defaultdict(<class 'int'>, {200: 2, 404: 1})}) 
+1

Этот ответ работает, но * Counter * внутри * defaultdict * является более чистым. –

2

попробовать это:

values = [['ip1',404], 
      ['ip1',200], 
      ['ip1',200], 
      ['ip2',200], 
      ['ip2',200], 
      ['ip2',504]] 

counts = {} 

for value in values: 
    ip, status_code = value 
    if ip not in counts: 
     counts[ip] = {} 
    if status_code not in counts[ip]: 
     counts[ip][status_code] = 0 
    counts[ip][status_code] += 1 

{'ip2': {200: 2, 504: 1}, 'ip1': {200: 2, 404: 1}} 

он должен работать практически на любой питона версии.

+1

+1 для обратной совместимости. 'dict.setdefault' сократил бы код и был настолько длинным, что, когда он был введен, в документах не упоминается! http://docs.python.org/library/stdtypes.html#dict.setdefault Например: 'ip, status_code в значениях: counts [ip] [status_code] = counts.setdefault (ip, {}). setdefault (status_code, 0) + 1' –

+0

@ NickCraig-Wood ничего себе, никогда новый, спасибо! –

0
L = [[ip1,404], [ip1,200], [ip1,200], [ip2,200], [ip2,200], [ip2,504]] 
D = {} 

for entry in L: 
    ip = entry[0] 
    code = entry[1] 
    ip_entry = D.get(ip, {}) 
    ip_entry[code] = ip_entry.get(code, 0) + 1 
    D[ip] = ip_entry 
Смежные вопросы