Home  >  Q&A  >  body text

python - 遍历list,转换成dict

我有一个list如下

[[['server', ''],['port','8800'],['location','/'],['location','/aa'],['location','bb']],[['server', ''],['port','80'],['location','/'],['location','/aa'],['location','bb']]]

想要得到如下的dict


[{'server': '','port': '8800','location': '/,/aa,/bb'},{'server': '','port': '80','location': '/,/aa,/bb'}]

或者

[{'server': '','port': '8800','location': '/'},{'server': '','port': '8800','location': '/aa'},{'server': '','port': '8800','location': '/bb'},{'server': '','port': '80','location': '/'},{'server': '','port': '80','location': '/aa'},{'server': '','port': '80','location': '/bb'}]

求解

之前有sf上的同学给出了一个例子

def turn2dic(lst):
    global key, value
    dic = {}
    if all([not isinstance(item, list) for item in lst]):
        if len(lst) == 2:
          key, value = lst
        elif len(lst) == 1:
          key=lst[0]
          value=''
        elif len(lst) == 3:
          key=lst[0]
          value=lst[1]
        dic[key] = value
    else:
        for item in lst:
            subdic = turn2dic(item)
            print subdic
            dic.update(subdic)
            print dic
    return dic

但是这个上面代码里,location是覆盖的,因为dic.update(subdic),有什么办法是append的?

PHP中文网PHP中文网2741 days ago426

reply all(4)I'll reply

  • 巴扎黑

    巴扎黑2017-04-17 17:56:02

    def single_turn2dic(lst):
        global key, value
        dic = {}
        if all([not isinstance(item, list) for item in lst]):
            if len(lst) == 2:
                key, value = lst
            elif len(lst) == 1:
                key = lst[0]
                value = ''
            elif len(lst) == 3:
                key = lst[0]
                value = lst[1]
                # dic[key] = value
            if value and dic.get(key, ''):
                dic[key] += ',' + value
            else:
                dic[key] = value
    
        else:
            for item in lst:
                subdic = single_turn2dic(item)
                # print subdic
                # dic.update(subdic)
                for name, name_value in subdic.iteritems():
                    if name_value and dic.get(name, ''):
                        dic[name] += ',' + name_value
                    else:
                        dic[name] = name_value
                        # print dic
        return dic
    
    
    servers = [[['server', ''], ['port', '8800'], ['location', '/'], ['location', '/aa'], ['location', 'bb']],
               [['server', ''], ['port', '80'], ['location', '/'], ['location', '/aa'], ['location', 'bb']]]
    
    
    def beautify(servers):
        # lst = []
        if not isinstance(servers[0][0], list):
    
            return single_turn2dic(servers)
        else:
            return [beautify(server) for server in servers]
            
    
    
    
    print beautify(servers)
    

    The general idea is [['server', ''], ['port', '8800'], ['location', '/'], ['location', '/aa'], ['location', 'bb']] This kind of processing is regarded as a unit (the function is modified from the code you gave), and the recursion is to the extent that it can be processed (because the number of layers may not be 2)

    reply
    0
  • PHP中文网

    PHP中文网2017-04-17 17:56:02

    Code:

    def turn2dic(lst):
        dic = {}
        if all([not isinstance(item, list) for item in lst]):
            key, value = lst
            dic[key] = value
        else:
            for item in lst:
                subdic = turn2dic(item)
                for key, value in subdic.items():
                    dic.setdefault(key, []).append(value)
        return dic
    
    results = [turn2dic(item) for item in lst]
    
    print results

    Result:

    [{'location': ['/', '/aa', 'bb'], 'port': ['8800'], 'server': ['']}, {'location': ['/', '/aa', 'bb'], 'port': ['80'], 'server': ['']}]
    1. I think unnecessary code can be removed. Since the problem this time is relatively simple (since it is determined that the bottom layer is a two-element list this time), there is no need to do too much judgment and processing (even this recursive solution can also be used) Change to a simple method).

    2. I'm not sure if there are any other repetitive things in your information besides location. I think it's better to process them uniformly, so the values ​​in my dictionary are different from the examples you gave. I use list instead of string. .

    reply
    0
  • 伊谢尔伦

    伊谢尔伦2017-04-17 17:56:02

    Break it apart to look better

    from collections import defaultdict
    
    def testtype(t):
        return lambda x: isinstance(x, t)
    
    def test(t, lst):
        return all(map(t if callable(t) else testtype(t), lst))
    
    def parse_dict(lst):
        dct = defaultdict(lambda: [])
        for k, v in lst:
            dct[k].append(parse(v))
        ret = {}
        for k, v in dct.items():
            if test(str, v):
                v = ','.join(v)
            elif len(v) == 1:
                v = v[0]
            ret[k] = v
            
        return ret
    
    def parse(obj):
        if not isinstance(obj, list):
            return obj
        if test(lambda x: len(x) == 2, obj):
            return parse_dict(obj)
        return list(map(parse, obj))
    
    src= [[['server', ''],['port','8800'],['location','/'],['location','/aa'],['location','bb']],[['server', ''],['port','80'],['location','/'],['location','/aa'],['location','bb']]]
    print(parse(src))

    reply
    0
  • ringa_lee

    ringa_lee2017-04-17 17:56:02

    Others have already taught you how to fish, so your level will not improve if you just ask for fish

    reply
    0
  • Cancelreply