4
\$\begingroup\$

As a challenge to myself, I wrote a solution to this Stack Overflow question. For completeness, the bulk of the question is as follows:

Problem

Input:

[
  ['key1', 'value1'],
  ['key2', 
     [
       ['key3', 'value3'],
       ['key4', 
          [
            ...
          ]
       ],
       ['key5', 'value5']
     ]
  ],
  ['key6', 'value6'],
]

Ouput:

{
  "key1": "value1",
  "key2": {
     "key3": "value3",
     "key4": ...,
     "key5": "value5"
  },
  "key6": "value6"
}

Solution

Please note that this is my first attempt.

import pprint

def main():
    lt = [ \
            ['key1', 'value1'], \
            ['key2', \
                [ \
                    ['key3', 'value3'], \
                    ['key4',  \
                        ['key7','value7'] \
                    ], \
                    ['key5', 'value5'] \
                ] \
            ], \
            ['key6', 'value6'] \
        ]
    print('Input:')
    pp = pprint.PrettyPrinter(indent=4)
    pp.pprint(lt)
    dt = lists2dict(lt, pp)
    print('-' * 80)
    print('Output:')
    pp.pprint(dt)

def lists2dict(lt, pp):
    # form a dict from a list of lists,
    # if a key's value is a single-element list, just add the element
    dt = {l[0]: l[1:] if len(l[1:]) > 1 else l[1] for l in lt}
    # print('-' * 70)
    # pp.pprint(dt)
    for k,v in dt.items(): # step through the dict, looking for places to recurse
        # print('k=%r, v=%r' %(k,v))
        if isinstance(v, list): # a value which is a list needs to be converted to a dict
            if isinstance(v[1], list): # only recurse if a to-be-parsed value has a list
                dt[k] = lists2dict(v, pp)
            else: # just a single k/v pair to parse
                dt[k] = {v[0]: v[1]}
    return dt

if __name__ == '__main__':
    main()

If anyone has improvements, or a more efficient and/or Pythonic implementation, please share it.

\$\endgroup\$
2
  • 2
    \$\begingroup\$ Argh! All the \ you are using when defining the input are useless. Also you should never us \ to continue a line since you can wrap whatever expression you are writing in parenthesis ( and ). \$\endgroup\$
    – Bakuriu
    Commented Dec 24, 2013 at 18:40
  • \$\begingroup\$ All brackets in Python ((, [, and {) begin implicit line continuation. There is no need to use `` to continue a line so long as it's enclosed in a pair of matching brackets. \$\endgroup\$
    – Iguananaut
    Commented Dec 26, 2013 at 19:28

1 Answer 1

6
\$\begingroup\$

You could simplify your function:

def nested_pairs2dict(pairs):
    d = {}
    for k, v in pairs:
        if isinstance(v, list): # assumes v is also list of pairs
           v = nested_pairs2dict(v)
        d[k] = v
    return d

It seems to work.

\$\endgroup\$
5
  • \$\begingroup\$ You could also shorten it further to def nested_pairs2dict(pairs): return dict((k, nested_pairs2dict(v) if isinstance(v, list) else v) for k, v in pairs) \$\endgroup\$ Commented Dec 24, 2013 at 21:13
  • 4
    \$\begingroup\$ @200_success: I find such one-liners less readable. \$\endgroup\$
    – jfs
    Commented Dec 24, 2013 at 21:14
  • \$\begingroup\$ Locally I get an error: for k,v in pairs // ValueError: too many values to unpack \$\endgroup\$
    – kevlar1818
    Commented Dec 24, 2013 at 21:41
  • \$\begingroup\$ @kevlar1818 Then you are not passing a list of 2-element lists to the function. \$\endgroup\$
    – poke
    Commented Dec 24, 2013 at 22:33
  • \$\begingroup\$ I'd also stick with the full version for long term maintenance. This example illustrates a great python principle: doing it right is usually shorter and cleaner than doing it wrong :) \$\endgroup\$
    – theodox
    Commented Dec 25, 2013 at 1:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.