0

I am looking to perform a reduce operation as part of a pipe to sort dict items based on a key. e.g.

from toolz import pipe

items = [{"id":1, "val":1}, {"id":2, "val":2}, {"id":2, "val":3}]
res = pipe(items, reduce(combine_items), other_ops...)
# res = {1: [{'id': 1, 'val': 1}], 2: [{'id': 2, 'val': 2}, {'id': 2, 'val': 3}]}

def combine_items(record_list, item):
    record_list.setdefault(item.get("id"), []).append(item)
    return record_list

I've managed to do this using a lambda i.e.

res = pipe(items, lambda x: reduce(combine_items, x, {}), other_ops...)

My question is whether there is another way I can do this without having to use a lambda within the pipe?

The main issue I have is that I need a default value for my list append to work properly within the reduce and I am unsure if there is a way to fill this correctly within the pipe otherwise.

monsia
  • 23
  • 5

1 Answers1

1

Rather than rolling your own combine_items, you can use groupby() from toolz which does exactly what you're trying to do here:

from toolz import groupby

res = groupby('id', items)

If you want to use that as part of a pipe, then you can use functools.partial() to pass groupby() a key argument:

from toolz import groupby, pipe
from functools import partial

res = pipe(items, partial(groupby, 'id'), other_ops...)
filbranden
  • 8,522
  • 2
  • 16
  • 32
  • 1
    I would go a step further - import curried toolz functions (`from toolz.curried import groupby, pipe`) and then you can write just `res = pipe(items, groupby('id'), other_ops...)` – Jan Spurny May 17 '21 at 17:36