【问题标题】:Visual C# Collection "map" function?Visual C# 集合“地图”功能?
【发布时间】:2013-11-06 17:37:55
【问题描述】:

在 Haskell 中我们有函数

map (a -> b) -> [a] -> [b]

使用函数更改集合的类型。

C#中有类似的东西吗?

或者,例如,将完整的 KeyValuePair 集合放入调试消息中的最快方法是什么?

我想到了类似的东西

debugmsg("http response is " + service.HttpResponseHeaders
                                      .Map<string>((k, v) => k + "->" + v)
                                      .Aggregate((s, sx) => s + "," + sx)
                             + ". ");

【问题讨论】:

  • 请注意,一个标头可以有多个值。简单地连接值是行不通的

标签: c# visual-studio collections map


【解决方案1】:

在 LINQ 中,map 被命名为 Select。另外,请注意KeyValuePair&lt;TKey, TValue&gt; 的任何集合在Select 中只有一个参数;你必须把KeyValue拉出来。

service.HttpResponseHeaders.Select(kvp => kvp.Key + "->" + kvp.Value)
                           .Aggregate((s, sx) => s + "," + sx);

【讨论】:

  • 值是一个 IEnumerable。简单地连接字符串将导致 "String[]" 而不是实际值
  • 如果是这种情况(键值对中的Value 是一个集合),那么对值执行SelectMany a.k.a flatMap 应该可以解决问题。
  • 并非如此,您需要将单个标头名称与多个值组合在一起。一个操作是不够的。
  • 那么做kvp =&gt; kvp.Key + "-&gt;" + string.Join("-", kvp.Value) 应该足够好了。问题是关于map 虽然......
【解决方案2】:

正如其他人所指出的,您可以使用 Select 将一种类型映射到另一种类型。不过,最好使用String.Join 创建最终字符串,以避免创建无用的临时字符串。

.NET 中的字符串是不可变的,因此添加两个字符串会创建一个新字符串。另一方面,String.Join 在内部使用 StringBuilder 将数据添加到可变缓冲区并返回最终结果。

您应该注意,HttpResponseHeaders 包含每个键的多个值。仅将值转换为字符串是行不通的。

以下将从响应标头中创建一个以逗号分隔的值列表。如果 header 有多个值,则用 '|' 分隔:

var headerStrings=from header in service.HttpResponseHeaders
            let headerValue=String.Join("|",header.Value)
            select String.Format("{0} -> {1}",header.Key,headerValue);
var message=String.Join(",",headerStrings);

【讨论】:

    【解决方案3】:

    您可以使用Dictionary,它基本上是KeyValuePairs 的集合并执行以下操作:

    service.HttpResponseHeaders
                      .Select(kvp => kvp.Key + " -> " + String.Join(" - ", kvp.Value))
                      .Aggregate((s, sx) => s + ", " + sx);
    

    优化聚合:Optimizing Aggregate for String Concatenation

    【讨论】:

    • HttpResponseHeaders 也是 KeyValuePair 的集合,实际上它实现了 IEnumerable>>。不需要Dictionary,字符串连接会返回“String[]”,而不是header值
    • 然后致电.Aggregate() 了解您的价值。看看我的编辑。
    • String.Join 会更简单更快,因为它不会创建任何临时字符串
    • 你确定 .Aggregate() 可以吗?为什么它不应该也使用StringBuilder
    • 除了DRY,试一试看看有多丑
    【解决方案4】:

    您可以使用.Select(),或者如果它是一个列表,您可以使用.ConvertAll()

    这是 MSDN 文档

    Enumerable.Select

    List.ConvertAll

    【讨论】:

      【解决方案5】:

      LINQ 自带Select

      签名(Haskell 风格):

      IEnumerable<TSource>.Select(Func<TSource->TResult>)->IEnumerable<TResult>
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-05-23
        • 2019-06-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-07-07
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多