Pythonic way to split a list of lists into a dictionary with long keys?

xs = [
        [1,2,3,4],
        [5,6,7,8],
        [9,0,0,1],
        [2,3],
        [0],
        [5,8,3,2,5,1],
        [6,4],
        [1,6,9,9,2,9]
]

""" expected output:

    xs_dict = {
        1: [[0]]
        2: [[2,3],[6,4]]
        4: [[1,2,3,4],[5,6,7,8],[9,0,0,1]]
        6: [[5,8,3,2,5,1],[1,6,9,9,2,9]]
    }
"""

      

I can do this for example

xs_dict = {}
for x in xs:
    aux = xs_dict.get(len(x),[])
    aux.append(x)
    xs_dict[len(x)] = aux

print(xs_dict)

      

But I can't help but feel that there must be a more pythonic way to achieve this.

What is it?

+3


source to share


4 answers


from itertools import groupby

xs_dict = {
    key: list(value)
    for (key, value) in groupby(sorted(xs, key=len), len)
}

      



As discussed in the comments below, the required input sort is a step that is unnecessarily costly. For large inputs, this will slow down this algorithm more than necessary. Use @ hiroprotagonist's solution instead, or replace groupby(sorted(…), …)

with groupby()

one that can handle unsorted input.

+6


source


you can use defaultdict

:

from collections import defaultdict

xs_dict = defaultdict(list)
for item in xs:
    xs_dict[len(item)].append(item)

      



python dict

also has a nice method setdefault

(this way you don't need to import anything):

xs_dict = {}
for item in xs:
    xs_dict.setdefault(len(item), []).append(item)

      

+5


source


import pprint
from collections import defaultdict
from itertools import groupby

xs = [
    [1, 2, 3, 4],
    [5, 6, 7, 8],
    [9, 0, 0, 1],
    [2, 3],
    [0],
    [5, 8, 3, 2, 5, 1],
    [6, 4],
    [1, 6, 9, 9, 2, 9]
]

data = defaultdict(list)

for result, group in groupby(sorted(xs, key=len), len):
    for item in group:
        data[result].append(item)

pprint.pprint(dict(data))

      

Gives me

{1: [[0]],
 2: [[2, 3], [6, 4]],
 4: [[1, 2, 3, 4], [5, 6, 7, 8], [9, 0, 0, 1]],
 6: [[5, 8, 3, 2, 5, 1], [1, 6, 9, 9, 2, 9]]}

      

0


source


1 liner:

res = {len(s): [d for d in xs if len(d) == len(s)] for s in xs}

      

0


source







All Articles