A powerful LINQ extension library that enhances ILookup with additional operations like Union, Intersect, Except, Join, Zip, and more. Includes fluent builder pattern and support for custom comparers.
A powerful LINQ extension library that enhances ILookup<TKey, TValue> with additional operations like Union,
Intersect, Except, Join, Zip, and more.
dotnet add package Orionde.MoreLookupusing Orionde.MoreLookup;
// Create lookups using the builder
var lookup1 = Lookup.Builder
.WithKey("fruits", new[] { "apple", "banana" })
.WithKey("colors", new[] { "red", "yellow" })
.Build();
var lookup2 = Lookup.Builder
.WithKey("fruits", new[] { "orange", "apple" })
.WithKey("animals", new[] { "cat", "dog" })
.Build();
// Union lookups
var union = lookup1.Union(lookup2);
// Result: fruits -> [apple, banana, orange], colors -> [red, yellow], animals -> [cat, dog]
// Intersect lookups
var intersection = lookup1.Intersect(lookup2);
// Result: fruits -> [apple]
// Filter values
var filtered = lookup1.Where(value => value.StartsWith("a"));
// Result: fruits -> [apple], colors -> []
// Transform values
var transformed = lookup1.Select(value => value.ToUpper());
// Result: fruits -> [APPLE, BANANA], colors -> [RED, YELLOW]Union(other) - Combines lookups, merging values for common keysIntersect(other) - Returns only values that exist in both lookups for common keysExcept(other) - Returns values from first lookup excluding those in secondConcat(other) - Concatenates all values for matching keysSelect(selector) - Projects each value using the selector functionWhere(predicate) - Filters values based on the predicateOnEachKey(func) - Applies a transformation function to each key's valuesJoin(inner, resultSelector) - Performs an inner join between lookupsZip(other, resultSelector) - Combines corresponding elements from both lookupsToDictionary() - Converts lookup to Dictionary<TKey, List<TValue>>ToLookup() - Extension for IEnumerable<IGrouping> and dictionariesLookup.Empty<TKey, TValue>() - Creates an empty lookup (singleton)Lookup.Builder - Fluent builder for creating lookups// Case-insensitive string comparer
var lookup = Lookup.Builder
.WithComparer(StringComparer.OrdinalIgnoreCase)
.WithKey("Test", new[] { "value1" })
.WithKey("TEST", new[] { "value2" }) // Will merge with previous key
.Build();
// Union with custom key comparer
var result = lookup1.Union(lookup2, keyComparer: StringComparer.OrdinalIgnoreCase);var result = from value in lookup
where value.Length > 3
select value.ToUpper();// Convert dictionary to lookup
var dict = new Dictionary<string, string[]>
{
["fruits"] = new[] { "apple", "banana" },
["colors"] = new[] { "red", "blue" }
};
var lookup = dict.ToLookup();
// Convert lookup back to dictionary
var backToDict = lookup.ToDictionary();This library was inspired by the original NOtherLookup project by NOtherDev. Special thanks to the author for the foundational concepts and the excellent blog post: "NOtherLookup - even better lookups".
While maintaining compatibility with modern .NET versions, this library builds upon those original ideas with:
MoreLinq is an excellent general-purpose LINQ extension library, but it focuses
primarily on IEnumerable<T> operations rather than ILookup<TKey, TValue> specifically. Key differences:
Use MoreLinq when: You need general sequence operations
Use Orionde.MoreLookup when: You're working extensively with lookups and need operations like Union, Intersect,
Except on grouped data
This library fills a specific gap by providing:
ILookup<TKey, TValue>This project is licensed under the MIT License - see the LICENSE file for details.
Contributions are welcome! Please feel free to submit a Pull Request.