【问题标题】:What is an easy way to append or prepend a single value to an IEnumerable<T>?将单个值附加或附加到 IEnumerable<T> 的简单方法是什么?
【发布时间】:2010-08-04 18:29:21
【问题描述】:

我需要在 IEnumerable 前添加一个值(在本例中为 IEnumerable&lt;string[]&gt;)。为了做到这一点,我创建了一个List&lt;T&gt; 只是为了包装第一个值,以便我可以调用Concat

// get headers and data together
IEnumerable<string[]> headers = new List<string[]> {
    GetHeaders()
};
var all = headers.Concat(GetData());

哎呀。有没有更好的办法?以及如何处理附加值的相反情况?

【问题讨论】:

    标签: c# linq ienumerable


    【解决方案1】:

    我为此编写了自定义扩展方法:

    public static IEnumerable<T> Append<T>(this IEnumerable<T> source, T item)
    {
        foreach (T i in source)
            yield return i;
    
        yield return item;
    }
    
    public static IEnumerable<T> Prepend<T>(this IEnumerable<T> source, T item)
    {
        yield return item;
    
        foreach (T i in source)
            yield return i;
    }
    

    在你的场景中,你会写:

    var all = GetData().Prepend(GetHeaders());
    

    正如chilltemp 所评论的,这不会改变原始集合。以真正的 Linq 方式,它会生成一个新的 IEnumerable&lt;T&gt;

    注意:建议对source 进行急切的空参数检查,但为简洁起见未显示。

    【讨论】:

    • 不错!我的图书馆里也有一些类似的。
    • 优雅。需要注意的是,这将通过枚举现有集合返回一个新的 IEnumerable。它实际上并没有附加/前置原始集合。
    • 请注意,Append 和 Prepend 从 4.7.1 开始在 .NET 中内置。 Check this answer
    【解决方案2】:

    使用Enumerable.Concat 扩展方法。对于附加值而不是前置,您只需反向调用Concat。 (即:GetData().Concat(GetHeaders());

    如果GetHeaders() 返回单个字符串数组,我个人可能会将其包装在单个元素数组而不是列表中:

     var all = (new[] {GetHeaders()}).Concat(GetData());
    

    【讨论】:

    • GetHeaders() 返回string[],GetData() 返回IEnumerable&lt;string&gt;。你读过我的问题吗?
    • @Gabe:这将适用于 string[] 和 IEnumerable - 数组实现 IEnumerable。但是,如果您的 string[] 是 string,情况就有些不同了。你的问题在这里不是很清楚。
    • @Gabe:我仍然不确定您到底想要什么 - 我进行了另一个编辑,向您展示了如何将所有元素保存为数组...
    • @Reed 和我的评论是错误的 - GetData() 返回IEnumerable&lt;string[]&gt;,很抱歉造成混淆。不过,您应该能够从我的问题中推断出类型。
    【解决方案3】:

    Rx 包含 StartWith 方法,该方法将值添加到序列中。 Return 也可以将值包装为序列,因此可以通过 Concat 附加。

            var c = new[] {4};
            var c1 = c.StartWith(1, 2, 3);
            var c2 = c1.Concat(EnumerableEx.Return(5));
    
            c2.Run(Console.Write); // 12345
    

    【讨论】:

      【解决方案4】:

      另一个选项是从单个项目创建序列的辅助方法:

      public static class EnumerableExt
      {
          public static IEnumerable<T> One<T>(T item)
          {
              yield return item;
          }
      }
      
      ...
      //prepend:
      EnumerableExt.One( GetHeaders() ).Concat( GetData() );
      
      //append:
      GetData().Concat( EnumerableExt.One( GetHeaders() );
      

      【讨论】:

        【解决方案5】:

        .NET 4.7.1 和更新版本最简单、最干净的方法是使用无副作用的Prepend()Append()

        例子

        // Creating an array of numbers
        var numbers = new[] { 1, 2, 3 };
        
        // Prepend and Append any value of the same type
        var results = numbers.Prepend(0).Append(4);
        
        // output is 0, 1, 2, 3, 4
        Console.WriteLine(string.Join(", ", results ));
        

        【讨论】:

          猜你喜欢
          • 2022-08-20
          • 1970-01-01
          • 1970-01-01
          • 2019-04-26
          • 2012-09-13
          • 2010-09-06
          • 2010-12-01
          • 1970-01-01
          • 2013-02-21
          相关资源
          最近更新 更多