如何以最易读的方式使用 LanguageExt 在 C# 中构建嵌套的 HashMap?

How to build nested HashMap in C# using LanguageExt in a most-readable way?

在 .NET/C# 中,我有 IEnumerable<T> 类型的输入数据,T 具有一些我想用于查找的属性。

如何使用 LanguageExt 构建两级(也许三级)查找而不产生像这样难以阅读的代码:

var items = Range(1, 1000)
            .Map(i => new 
                 {
                   Number = i, 
                   Section = (byte) (i % 10), 
                   Text = $"Number is i"
                 }); // just some test data

HashMap<byte, HashMap<int, string>> lookup 
  = toHashMap(
      from item in items
      group item.Text by (item.Section, item.Number) into gInner
      group gInner by gInner.Key.Section into gOuter
      select ( gOuter.Key, toHashMap(gOuter.Map(_ => (_.Key.Number, _.Head()))) )
    );

预期输出:使用 Section 作为外键、Number 作为内键和 Text 作为值的查找 hashmap。

我更喜欢使用 LINQ 语法的解决方案(可能更容易将其与转换/过滤/排序结合起来......)。

Language-ext has built-in extension methods 用于处理嵌套的 HashMapMap 类型(最多四个嵌套级别):

因此,要查找类型:

HashMap<int, HashMap<string, DateTime>> lookup = ...;

var value = lookup.Find(123, "Hello");

您还可以添加:

lookup = lookup.AddOrUpdate(123, "Hello", value);

还有RemoveMapRemoveTMapTFilterTFilterRemoveTExistsForAllSetItemTTrySetItemTFoldT

因此,回答您的具体问题:

var map = items.Fold(
            HashMap<byte, HashMap<int, string>>(), 
            (s, item) => s.AddOrUpdate(item.Section, item.Number, item.Text));

如果你经常这样做,那么你可以将它概括为 Seq<(A, B, C)>

的扩展
public static HashMap<A, HashMap<B, C>> ToHashMap<A, B, C>(this Seq<(A, B, C)> items) =>
    items.Fold(
        HashMap<A, HashMap<B, C>>(), 
        (s, item) => s.AddOrUpdate(item.Item1, item.Item2, item.Item3));

我有同样的要求,这就是我将这些添加到 language-ext 的原因:)