【问题标题】:Concatenate Split Array from Select Field in LINQ从 LINQ 中的选择字段连接拆分数组
【发布时间】:2014-04-14 14:40:12
【问题描述】:

我有一个字符串元素列表,每个元素都可以包含一个逗号分隔的值列表。由此,我想生成整个集合中所有不同值的列表。

以下面一组字符串为例:

Dim strings = New List(Of String) From {"A", "B,C,D", "D,E"}

我想把它变成:

{"A", "B", "C", "D", "E"}

使用 linq,我可以获取每个元素并将其转换为字符串数组。以下查询只会将每个字符串拆分为一个数组,但它会保留在它自己的数组元素中。

Dim fieldsLinq = (From s In strings
                  Select s.Split(",")) _
                 .Distinct()

我想将所有值连接成一个字符串数组。

我可以先用逗号连接所有元素,然后拆分单个字符串,但这感觉是错误的方法。

Dim fieldsJoin = String.Join(",", strings) _
                       .Split(",") _
                       .Distinct()

有没有更好的解决方案?

【问题讨论】:

    标签: .net vb.net linq


    【解决方案1】:

    我不太了解 VB,但您可以使用 SelectMany 来展平数组。在 C# 中

    strings.SelectMany(o=>o.Split(","));
    

    【讨论】:

    • 你可以这样做:strings.SelectMany(x => x.Split(',')).Distinct()
    • 完美,这正是我想要的!谢谢
    • @KyleMit 太棒了。除非你很高兴,否则请
    • @Murdock,我很高兴接受并支持您的回答,但作为仅供参考,您不应该觉得有必要要求其他用户采取投票行动,尤其是在被问到的第一个小时内。
    • @KyleMit 我的道歉
    【解决方案2】:

    我想Aggregate 可以解决问题:

    Dim fieldsAggregate = strings.Aggregate(New List(Of String), 
                                            Function(seed, s) 
                                                seed.AddRange(s.Split(","))
                                                Return seed
                                            End Function).Distinct()
    

    更新:这是 murdock 答案的 VB 版本,在 lambda 和查询语法中使用 SelectMany

    Dim lambda = strings.SelectMany(Function(s) s.Split(",")) _ 
                        .Distinct()
    
    Dim query = (From outer In strings
                 From inner In outer.Split(",")
                 Select inner) _
                .Distinct()
    

    【讨论】:

      【解决方案3】:

      我知道这可能与原始问题无关,但对于来到此页面寻找解决此问题的好方法的用户可能仍然有用。在我看来,LINQ 应该让开发者的生活更简单、更短、更长远。

      在这种特殊情况下,替代方法(即不使用 LINQ)已经非常简单,并且更易于维护。通常,如果您输入了 "A,B,D" 之类的数据,从长远来看,您将面临维护噩梦,因此您的 LINQ 查询可能很快就会被扩展到一个大怪物。

      考虑这段代码,它做同样的事情(老派开始了):

      Private Shared Function AggregateSplit(input As List(Of String)) _
                                                                   As List(Of String)
        Dim hsItems As New HashSet(Of String)
        For Each s As String In input
          AddRangeToHashSet(hsItems, s.Split(","))
        Next
        Return hsItems.ToList
      End Function
      
      Private Shared Sub AddRangeToHashSet(hsItems As HashSet(Of String),
                                           items As IEnumerable(Of String))
        For Each s As String In items
          If hsItems.Contains(s) Then Continue For
          hsItems.Add(s)
        Next
      End Sub
      

      用法:

      Dim r = AggregateSplit(strings)
      

      理想情况下,您已经将AddRangeToHashSet 作为扩展方法,因此您无需在每次需要AddRange 时都定义它。因此,在这种情况下,您只需声明 AggregateSplit。对于不熟悉 LINQ 的人来说,解释它在做什么也容易得多,如果解析不好,您可以调试。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-08-27
        • 1970-01-01
        • 1970-01-01
        • 2023-03-06
        • 1970-01-01
        相关资源
        最近更新 更多