https://github.com/notherdev/notherlookup
Set of extensions for easy creation and manipulation of ILookups
https://github.com/notherdev/notherlookup
Last synced: 3 months ago
JSON representation
Set of extensions for easy creation and manipulation of ILookups
- Host: GitHub
- URL: https://github.com/notherdev/notherlookup
- Owner: NOtherDev
- License: mit
- Created: 2014-01-09T21:04:18.000Z (over 12 years ago)
- Default Branch: master
- Last Pushed: 2014-01-18T21:59:19.000Z (over 12 years ago)
- Last Synced: 2025-04-08T14:03:19.933Z (about 1 year ago)
- Language: C#
- Homepage:
- Size: 1.45 MB
- Stars: 9
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# NOtherLookup
NOtherLookup is a set of LINQ-like extensions that are aimed to make working with [the splendid `ILookup`](http://notherdev.blogspot.com/2014/01/lookup-hidden-gem.html) even easier. It tries to resolve [two main `ILookup`'s deficiencies](http://notherdev.blogspot.com/2014/01/downsides-of-net-lookups.html) - lack of easy way to create it from the scratch and lack of easy way to apply transformations.
## Table of Contents
* [Creating `ILookup`](#creating-ilookup)
* [Empty `ILookup`](#empty-ilookup)
* [Creating `ILookup` manually - `Lookup.Builder`](#creating-ilookup-manually---lookupbuilder)
* [Converting `ILookup` from/to `IDictionary`](#converting-ilookup-fromto-idictionary)
* [Manipulating single `ILookup`](#manipulating-single-ilookup)
* [`Select` - runs a projection on values for each key](#select---runs-a-projection-on-values-for-each-key)
* [`Where` - filters values for each key](#where---filters-values-for-each-key)
* [`OnEachKey` - runs arbitrary LINQ query on lookup elements (`IGrouping`s)](#oneachkey---runs-arbitrary-linq-query-on-lookup-elements-igroupings)
* [Manipulating two `ILookup`s](#manipulating-two-ilookups)
* [`Concat` - concatenates values for each key](#concat---concatenates-values-for-each-key)
* [`Union` - gets the unique values for each key](#union---gets-the-unique-values-for-each-key)
* [`Except` - gets the difference of values set for each key](#except---gets-the-difference-of-values-set-for-each-key)
* [`Intersect` - gets the intersection of values set for each key](#intersect---gets-the-intersection-of-values-set-for-each-key)
* [`Join` - combines two lookups by values in each key using provided selector](#join---combines-two-lookups-by-values-in-each-key-using-provided-selector)
* [`Zip` - combines two lookups by pairs of values using provided selector for each key](#zip---combines-two-lookups-by-pairs-of-values-using-provided-selector-for-each-key)
## Creating `ILookup`
.NET's [`Lookup`](http://msdn.microsoft.com/en-us/library/bb460184\(v=vs.110\).aspx) class has no public constructor. NOtherLookup offers several ways to obtain an `ILookup` instance.
### Empty `ILookup`
Useful to keep the code clean and obvious.
ILookup emptyLookup = Lookup.Empty();
### Creating `ILookup` manually - `Lookup.Builder`
ILookup lookup = Lookup.Builder
.WithKey(1, new[] { "a", "b" })
.WithKey(2, new[] { "c", "d" })
.Build();
Allows specifying a custom key comparer:
ILookup lookup = Lookup.Builder
.WithComparer(new CustomComparer())
.WithKey(1, new[] { "a", "b" })
.WithKey(2, new[] { "c", "d" })
.Build();
### Converting `ILookup` from/to `IDictionary`
IDictionary sourceDictionary = new Dictionary()
{
{ 1, new[] { "a", "b" }},
{ 2, new[] { "c", "d" }}
};
Converting dictionaries to lookups works for multiple types of `TValue` collections - `TValue[]`, `ICollection` and `IList` - as well as for `IEnumerable>` (decomposed lookup).
ILookup lookup = sourceDictionary.ToLookup();
And back to mutable `IDictionary` - doable using standard LINQ operators, but quite verbose and convoluted.
Dictionary> backToDict = lookup.ToDictionary();
## Manipulating single `ILookup`
Contrary to what we get using standard LINQ operators on `ILookup`, all the operators below maintains `ILookup` typing.
Lookup instance used in the examples:
ILookup lookup = Lookup.Builder
.WithKey(1, new[] { "a", "b" })
.WithKey(2, new[] { "c", "d" })
.Build();
### `Select` - runs a projection on values for each key
ILookup projected = lookup.Select(x => x + "!");
Result:
1 => [a!, b!]
2 => [c!, d!]
### `Where` - filters values for each key
ILookup filtered = lookup.Select(x => x != "a");
Result:
1 => [b]
2 => [c, d]
### `OnEachKey` - runs arbitrary LINQ query on lookup elements (`IGrouping`s)
It is a generalization for any transformation that is supposed to run on each key in lookup. Note that `Select` and `Where` can be also easily accomplished through `OnEachKey` - they are standalone methods only for convenience.
ILookup transformed = lookup.OnEachKey(g => g.Select(x => x + g.Key).Reverse());
Result:
1 => [b1, a1]
2 => [d2, c2]
## Manipulating two `ILookup`s
Contrary to what we get using standard LINQ operators on `ILookup`, all the operators below maintains `ILookup` typing.
The operators allow specifying custom key comparers, where applicable.
Lookup instances used in the examples:
ILookup first = Lookup.Builder
.WithKey(1, new[] { "a", "b" })
.WithKey(2, new[] { "c", "d" })
.Build();
ILookup second = Lookup.Builder
.WithKey(1, new[] { "a", "c" })
.WithKey(3, new[] { "e", "f" })
.Build();
### `Concat` - concatenates values for each key
ILookup concatenated = first.Concat(second);
Result:
1 => [a, b, a, c]
2 => [c, d]
3 => [e, f]
### `Union` - gets the unique values for each key
ILookup unionized = first.Union(second);
Result:
1 => [a, b, c]
2 => [c, d]
3 => [e, f]
Also supports custom values comparers.
### `Except` - gets the difference of values set for each key
ILookup difference = first.Except(second);
Result:
1 => [b]
2 => [c, d]
Also supports custom values comparers.
### `Intersect` - gets the intersection of values set for each key
ILookup intersection = first.Intersect(second);
Result:
1 => [a]
Also supports custom values comparers.
### `Join` - combines two lookups by values in each key using provided selector
ILookup joined = first.Join(second, (x, y) => x + y);
Result:
1 => [aa, ac, ba, bc]
### `Zip` - combines two lookups by pairs of values using provided selector for each key
ILookup zipped = first.Zip(second, (x, y) => x + y);
Result:
1 => [aa, bc]