简体   繁体   中英

converting a list of lists ina dictionary where inner lists are key-value pairs

I have a list of lists:

[['a', 1],['b', 2]['c', 3]['c', 1]['c', 9]['d', 8]['d', 4]]

I want to make a dictionary with :

{ a:1, b:2, c:[3,1,9],d:[8,9]}

I have tried the following:

count = 0
sw_fd_dict = {}
value_list =[]  
sw_fd_list2 = [['a', 1],['b', 2],['c', 3],['c', 1],['c', 9],['d', 8],['d', 4]]
while count < len(sw_fd_list2):
    try:
        # to check for repeated keys like "c"
        if sw_fd_list2[count][0] != sw_fd_list2[count-1][0]: 
            sw_fd_dict[sw_fd_list2[count][0]] = sw_fd_list2[count][1]

        elif sw_fd_list2[count][0] == sw_fd_list2[count-1][0]:
            value_list.append(sw_fd_list2[count-1][1])
            value_list.append(sw_fd_list2[count][1])
            sw_fd_list2[count][1] =value_list
            sw_fd_dict[sw_fd_list2[count][0]] = sw_fd_list2[count][1]

      except Exception as e:
          print str(e)
      count += 1
print sw_fd_dict

Is there a better way to do this?

This is a shorter approach:

result = {}
for (key, value) in the_list:
    result.setdefault(key, []).append(value)

setdefault returns the value (like get ) but sets it first if it's not present. ( defaultdict also works fine here.)

On rereading the question, if you really want the single numbers to not be lists, you can put in some more conditions. I edited this to use a set rather than checking whether the existing value was appendable, in order to be 'safe' in case your values are collections rather than numbers.

result = {}
seen = set()
for (key, value) in the_list:
    if key not in result:
        result[key] = value
    elif key not in seen:
        result[key] = [result[key], value]
        seen.add(key)
    else:
        result[key].append(value)

Or, a nice way of converting the defaultdict-style answer to the one with individual numbers not in lists:

result = {
    key: value[0] if len(value) == 1 else value
    for key, value in result.items()}

You can use defaultdict in the collections package:

from collections import defaultdict
sw_fd_dict = defaultdict(list)
sw_fd_list2 =  [['a', 1],['b', 2], ['c', 3], ['c', 1], ['c', 9], ['d', 8], ['d', 4]]

for key, val in sw_fd_list2:
    sw_fd_dict[key].append(val)

sw_fd_dict

Out[8]: defaultdict(<type 'list'>, {'a': [1], 'c': [3, 1, 9], 'b': [2], 'd': [8, 4]})

Then you convert it to a traditional dict :

dict(sw_fd_dict)
Out[9]: {'a': [1], 'b': [2], 'c': [3, 1, 9], 'd': [8, 4]}

EDIT: Quentin THEURET pointed out that I didn't replicate the exact results you want. Thanks to his comment, I've noticed that you require the single value to be an integer on its own, instead wrapped in a list. You can then perform some post-processing:

d = dict(sw_fd_dict)
for k in d.keys():
    if len(d[k]) == 1:
        d[k] = d[k][0]
d
Out[15]: {'a': 1, 'b': 2, 'c': [3, 1, 9], 'd': [8, 4]}
def list_to_dict(l):
    d = {}
    for key, val in l:
         if key in d:
             if isinstance(d[key], list):
                 d[key].append(val)
             else:
                 d[key] = [d[key], val]
         else:
             d[key] = val
    return d

sw_fd_list2 = [['a', 1],['b', 2],['c', 3],['c', 1],['c', 9],['d', 8],['d', 4]]
res = list_to_dict(sw_fd_list2)

Pretty similar question: https://stackoverflow.com/a/960753/1317856

>>> l = [['a', 1],['b', 2]['c', 3]['c', 1]['c', 9]['d', 8]['d', 4]]
>>> from collections import defaultdict
>>> d = defaultdict(list)
>>> for a, b in l:
    d[a].append(b)
>>> dict(d)
{'a': [1], 'c': [3, 1, 9], 'b': [2], 'd': [8, 4]}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM