【问题标题】:Adding an element to an array向数组中添加元素
【发布时间】:2010-06-30 03:01:39
【问题描述】:

我正在从源中读取数据作为数组。一个[n]

我需要在数组中再添加一个元素。

获得数组后,我创建一个容量为 n+1 的新数组,并将所有元素复制到新数组中,并将新元素作为数组的最后一个元素。

我能做到。

有没有更好的方法来做到这一点?尤其是 Linq?

【问题讨论】:

  • 请不要在标题中添加“C#”之类的标签。只需将标签留在标签中,这是标签所属的地方。

标签: c# .net linq arrays


【解决方案1】:

您所描述的确实是唯一的方法。数组不能在 .NET 中调整大小,因此我们必须分配一个新数组并将旧数组复制到其中。例如,Array.Resize 就是这样工作的。 LINQ 在这里并不是真正的帮助,如果是的话,它只是将现有数组投影到一个新数组中——这正是我们刚刚描述的。

如果您发现需要经常调整数组大小,您应该考虑使用ArrayList,或者如果可能,使用强类型List<T>

编辑: 如果您只是从某种您无法控制的方法中获取一个数组,但在您的代码中您可以使用 IEnumerable<T> 代替,您可以使用 LINQ 进行延迟枚举并节省额外的数组分配:

var mySequence = originalArray.Concat(new[]{myobj});

//snip

foreach(var item in mySequence)
{
    //do stuff
}

只有在调用ToArray() 时才会产生额外开销。否则,我们只是简单地对原始数组进行一次枚举,然后在最后偷偷添加额外的项目。

【讨论】:

  • 很遗憾,数据源返回数组,我无能为力。
  • @user 是什么阻止您在收到数据源后将其更改为列表?为什么要将它保留为一个不灵活的数组?
  • 因为我必须将它作为数组存储回来。所以把它改成一个列表然后再改回一个数组是不是有点矫枉过正?
  • @RexM 所以 Add() 方法的工作方式相同(创建新数组)?
  • @entropy 你指的Add 方法是什么?
【解决方案2】:

如果要使用 LINQ 将数组放在一起,可以使用 Concat:

var combined = array1.Concat(new[] { element }).ToArray();

但是,您现在正在为您的集合创建许多不同的数组。更好的选择是只使用一个列表。它将由单个数组支持并为您自动扩展。

【讨论】:

    【解决方案3】:

    C# yield(不需要额外的存储空间)

    使用C# yield 可以让您返回您的阵列等,而无需分配额外的存储空间。在产生原始数组的每个元素后,您可以像这样轻松地滑入任何额外的元素:

    IEnumerable<int> GetEverything() {
    
        // first return the entire original array
        foreach(int num in arrNumbers)
            yield return num;
    
        // then slip in extra element at the end
        yield return 5;   // yield even more elements if you want...
    }
    

    然后你可以像这样使用它:

    foreach (int n in GetEverything())
        Console.WriteLine(n);
    

    在这种情况下没有必要退出 LINQ,因为 yield 语句很简单并且完全适合您的需要。

    【讨论】:

      【解决方案4】:

      你可以只使用数组来初始化一个列表。

      var stuff = new List<object>( a );
      stuff.Add( moreStuff );
      

      【讨论】:

      • 你应该使用强类型列表。
      • SomeType替换object
      • OP 没有说明他正在使用什么类型,我假设他知道如何使用通用列表。这真的离题了。
      • 如果 OP 提出一个基本问题,比如是否有某种方法可以调整数组的大小,您不应该对他对通用集合的了解或对性能问题的了解做出任何假设通用集合中的铸造/装箱/拆箱对象。 FFS,声明 List 破坏了通用集合中的全部要点!此时您不妨使用 Arraylist。
      • 如果 OP 不理解泛型的目的,我的建议是完全停止这个项目并开始阅读初学者的教程。
      【解决方案5】:

      您可以为此使用Array.Resizehttp://msdn.microsoft.com/en-us/library/bb348051.aspx

      它基本上可以完成您手动完成的工作,但更整洁。

      如果您定期向数组中添加多个元素,我建议您移至列表,因为这样插入效率更高。

      【讨论】:

        【解决方案6】:

        改用List&lt;T&gt;,并调用myList.Add(item)

        编辑:如果您的意思是以数组的形式获取数据(而不是将数据读入其中),请使用 List 的构造函数从数组中复制。

        【讨论】:

          【解决方案7】:

          您可以使用 ToArray 和 ToList Linq 命令。

          这是一个通用方法,它将返回一个新数组,该数组将是原始数组和新项目的副本。

          public static T[] AddItem<T>( T[] array, T item )
          {
              List<T> list = array.ToList();
              list.Add( item );
              return list.ToArray();
          }
          

          这是一个将项目添加到数组中的通用扩展方法。 (该数组将是内存中的一个新数组,因此可能会产生副作用)。

          public static void AddItem<T>( this T[] array, T item )
          {
              List<T> list = array.ToList();
              list.Add( item );
              array = list.ToArray(); /* Untested, this may not compile! */
          }
          

          【讨论】:

          • 这比简单地将旧数组直接复制到新数组中要差一些。
          • 我同意这可能不是处理此问题的最有效方法。我喜欢你使用 Concat 方法。我忽略了那个。我对你的答案投了赞成票。
          • 您是否实际测试过该扩展方法?因为如果它有效,则意味着 this 参数通过引用传递,这让我感到惊讶。
          • @Isaac,不幸的是我没有测试那个例程,这是事后的想法。
          • 我更新了代码示例,让别人知道它可能不起作用。我决定离开它,因为我认为对此的扩展方法可能仍然是一个很好的解决方案。
          【解决方案8】:

          如果你必须使用相同类型的数组 {ArrayVar1,ArrayVar2}

          ,你可以使用类似的东西
          var arrayList = ArrayVar1.ToList();
          arrayList.AddRange(ArrayVar2); // or for single element use arrayList.Add(Var2);
          ArrayVar1=arrayList.ToArray();
          

          【讨论】:

            【解决方案9】:

            使用数组方法 Resize 和 ConstrinedCopy 的示例。无需制作额外的数组。

            Filter[] filterA = new Filter[] {
                  new Filter() { field = "trans_date", Data = "2018-01-01", Op = "gt" }
                  , new Filter() { field = "trans_date", Data = "2018-01-02", Op = "gt" }
                  , new Filter() { field = "trans_date", Data = "2018-01-03", Op = "gt" }
            };
            
            Filter[] filterB = new Filter[] {
                  new Filter() { field = "trans_date", Data = "2018-01-04", Op = "gt" }
                  , new Filter() { field = "trans_date", Data = "2018-01-05", Op = "gt" }
            };
            
            
            //resizing the original array to hold all the new elements.
            Array.Resize(ref filterA, filterA.Length + filterB.Length);
            
            //take the items from filterB and place them in filterA
            Array.ConstrainedCopy(filterB, 0, filterA, 3, 2);
            

            【讨论】:

              猜你喜欢
              • 2014-08-03
              • 2012-03-23
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2022-01-20
              • 2011-08-11
              • 2015-09-02
              • 2012-04-20
              相关资源
              最近更新 更多