Skip to content

BatchBy : Build up buckets by key. #657

Open
@Orace

Description

@Orace

Derived from Dispatch #633 which can surely only be chained with a Zip, BatchBy combine Dispatch and Zip to builds up buckets that are dictionaries.

IEnumerable<Dictionary<TKey, TValue>> BatchBy<TKey, TValue>(
  this IEnumerable<TValue> source,
  Func<TValue, TKey> keySelector,
  IEnumerable<TKey> acceptedKeys);

An example of use:

Let says that you have the logs of a connection between a client and a server.
All client request start with Q and all server response start with A.
There is also some noise that start with #.

  Q> Hy
  A> Hello
  Q> What's your name ?
  #> the fuzz is buzzing
  Q> And city ?
  A> My name is Bob
  Q> And age
  #> the buzz is fuzzing
  A> I live in Detroit
  A> I'm 42
  ...

That is the input of type IEnumerable<string>
We want to match each Q with it's corresponding A.

We can do it with BatchBy like this:

var keys = new[] {'Q', 'A'};
var batches = intput.BatchBy(s => s.FirstOrDefault(), keys);

With the example data bellow, batches will yield those dictionaries:

  {{Key: 'Q', Value: "Q> Hy"}, {Key: 'A', Value: "A> Hello"}},
  {{Key: 'Q', Value: "Q> What's your name ?"}, {Key: 'A', Value: "A> My name is Bob"}},
  {{Key: 'Q', Value: "Q> And city ?"}, {Key: 'A', Value: "A> I live in Detroit"}},
  {{Key: 'Q', Value: "Q> And age"}, {Key: 'A', Value: "A> I'm 42"}},
  ...

remark
In the example bellow Q always come before A, it may be otherwise, the batches are yield when they have a matching value for each key.

Overload with a static number of keys are possible:

IEnumerable<TResult> BatchBy<TKey, TValue, TResult>(
  this IEnumerable<TValue> source,
  Func<TValue, TKey> keySelector,
  TKey key1,
  ...,
  TKey keyN,
  Func<TKey, ..., TKey, TResult> resultSelector);

And can be used like this:

var batches = intput.BatchBy(s => s.FirstOrDefault(), 'Q', 'A', (Question, Answer) => (Question, Answer));

ValueTuple overload are also possibles:

IEnumerable<(TValue, ..., TValue)> BatchBy<TKey, TValue>(
  this IEnumerable<TValue> source,
  Func<TValue, TKey> keySelector,
  TKey key1,
  ...,
  TKey keyN);

To discuss

  • Arguments order
  • Case of N = 1 (witch is Where(v => keySelector(v) == v).Select(resultSelector))

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions