【问题标题】:Joining two lists together将两个列表连接在一起
【发布时间】:2010-12-04 10:21:20
【问题描述】:

如果我有两个字符串类型(或任何其他类型)的列表,那么连接这两个列表的快速方法是什么?

顺序应该保持不变。应删除重复项(尽管两个链接中的每个项目都是唯一的)。我在谷歌搜索时没有找到太多关于此的内容,并且不想实现任何 .NET 接口以加快交付速度。

【问题讨论】:

标签: c#


【解决方案1】:

你可以试试:

List<string> a = new List<string>();
List<string> b = new List<string>();

a.AddRange(b);

MSDN page for AddRange

这会保留列表的顺序,但不会像Union 那样删除任何重复项。

这确实改变了列表a。如果您想保留原始列表,那么您应该使用Concat(正如其他答案中所指出的那样):

var newList = a.Concat(b);

只要a 不为空,就会返回IEnumerable

【讨论】:

  • 没有人真正关心何时使用哪种方法。 AddRange 编辑一个列表,将第二个列表添加到其中(就像您多次调用 .Add(foo) 一样)。 Concat 和 Union 扩展方法不会更改原始列表。他们懒惰地构造一个新的 IEnumerable,除非必要,否则他们甚至不会访问原始列表成员。如前所述,Union 会删除重复项,而其他则不会。
  • 有谁知道这种方法的复杂性是什么? (很遗憾微软没有在他们的 MSDN 中提供这些重要信息)
  • 我建议您查看这个对各种方法的良好比较。还展示了各种选项的一些性能分析:Merge Collections
  • 这非常有效。在超过 50 万个项目上使用 concat(),这需要几分钟。这种方法只需不到 5 秒。
  • hi.. 如果列表为空,concat 函数是否返回 null?
【解决方案2】:

空间开销最小的方式是使用 Concat 扩展方法。

var combined = list1.Concat(list2);

它创建一个IEnumerable&lt;T&gt; 的实例,它将按该顺序枚举list1 和list2 的元素。

【讨论】:

  • 记得using System.Linq;才能使用Concat
【解决方案3】:

Union 方法可能会满足您的需求。您没有指定顺序或重复是否重要。

采用两个 IEnumerable 并执行联合,如下所示:

int[] ints1 = { 5, 3, 9, 7, 5, 9, 3, 7 };
int[] ints2 = { 8, 3, 6, 4, 4, 9, 1, 0 };

IEnumerable<int> union = ints1.Union(ints2);

// yields { 5, 3, 9, 7, 8, 6, 4, 1, 0 } 

【讨论】:

    【解决方案4】:

    类似这样的:

    firstList.AddRange (secondList);
    

    或者,您可以使用 System.Linq 中定义的“Union”扩展方法。 使用'Union',你还可以指定一个比较器,它可以用来指定一个项目是否应该联合。

    像这样:

    List<int> one = new List<int> { 1, 2, 3, 4, 5 };
    List<int> second=new List<int> { 1, 2, 5, 6 };
    
    var result = one.Union (second, new EqComparer ());
    
    foreach( int x in result )
    {
        Console.WriteLine (x);
    }
    Console.ReadLine ();
    
    #region IEqualityComparer<int> Members
    public class EqComparer : IEqualityComparer<int>
    {
        public bool Equals( int x, int y )
        {
            return x == y;
        }
    
        public int GetHashCode( int obj )
        {
            return obj.GetHashCode ();
        }
    }
    #endregion
    

    【讨论】:

    • +1 用于使用 EqualityComparer!我能够使用它来更好地处理我的自定义对象列表。
    【解决方案5】:
    targetList = list1.Concat(list2).ToList();
    

    我认为它工作正常。如前所述,Concat 返回一个新序列,在将结果转换为 List 时,它完美地完成了这项工作。使用 AddRange 方法时,隐式转换有时可能会失败。

    【讨论】:

      【解决方案6】:

      如果两个列表中都存在某些项目,您可以使用

      var all = list1.Concat(list2).Concat(list3) ... Concat(listN).Distinct().ToList();
      

      【讨论】:

        【解决方案7】:

        只要是同一类型,用AddRange就很简单了:

        list2.AddRange(list1);
        

        【讨论】:

          【解决方案8】:

          AddRange method

          aList.AddRange( anotherList );
          

          【讨论】:

            【解决方案9】:
            var bigList = new List<int> { 1, 2, 3 }
                .Concat(new List<int> { 4, 5, 6 })
                .ToList(); /// yields { 1, 2, 3, 4, 5, 6 }
            

            【讨论】:

            • 我也喜欢这个。很简单。谢谢。
            • 我喜欢这个,因为它不会改变任何一个列表。
            • 这像Union All吗?或不?如果所有列表中都存在数字 1 怎么办?
            • Concat 更多/更少“联合所有”
            【解决方案10】:
            List<string> list1 = new List<string>();
            list1.Add("dot");
            list1.Add("net");
            
            List<string> list2 = new List<string>();
            list2.Add("pearls");
            list2.Add("!");
            
            var result = list1.Concat(list2);
            

            【讨论】:

              【解决方案11】:

              一种方式:List.AddRange() 取决于类型?

              【讨论】:

                【解决方案12】:

                一种方式,我没有看到提到它可以更健壮,特别是如果你想以某种方式改变每个元素(例如你想.Trim()所有元素。

                List<string> a = new List<string>();
                List<string> b = new List<string>();
                // ...
                b.ForEach(x=>a.Add(x.Trim()));
                

                【讨论】:

                  【解决方案13】:

                  看到这个link

                  public class ProductA
                  { 
                  public string Name { get; set; }
                  public int Code { get; set; }
                  }
                  
                  public class ProductComparer : IEqualityComparer<ProductA>
                  {
                  
                  public bool Equals(ProductA x, ProductA y)
                  {
                      //Check whether the objects are the same object. 
                      if (Object.ReferenceEquals(x, y)) return true;
                  
                      //Check whether the products' properties are equal. 
                      return x != null && y != null && x.Code.Equals(y.Code) && x.Name.Equals(y.Name);
                      }
                  
                  public int GetHashCode(ProductA obj)
                  {
                      //Get hash code for the Name field if it is not null. 
                      int hashProductName = obj.Name == null ? 0 : obj.Name.GetHashCode();
                  
                      //Get hash code for the Code field. 
                      int hashProductCode = obj.Code.GetHashCode();
                  
                      //Calculate the hash code for the product. 
                      return hashProductName ^ hashProductCode;
                  }
                  }
                  
                  
                      ProductA[] store1 = { new ProductA { Name = "apple", Code = 9 }, 
                                     new ProductA { Name = "orange", Code = 4 } };
                  
                      ProductA[] store2 = { new ProductA { Name = "apple", Code = 9 }, 
                                     new ProductA { Name = "lemon", Code = 12 } };
                  

                  //从两个数组中获取产品 //排除重复。

                  IEnumerable<ProductA> union =
                    store1.Union(store2);
                  
                  foreach (var product in union)
                      Console.WriteLine(product.Name + " " + product.Code);
                  
                  /*
                      This code produces the following output:
                  
                      apple 9
                      orange 4
                      lemon 12
                  */
                  

                  【讨论】:

                    【解决方案14】:

                    我使用的两个选项是:

                    list1.AddRange(list2);
                    

                    list1.Concat(list2);
                    

                    但是我注意到,当我使用带有递归函数的 AddRange 方法时,它经常调用自身,因为达到了最大维数,所以我得到了 SystemOutOfMemoryException。

                    (消息 Google 翻译)
                    数组尺寸超出了支持的范围。

                    使用Concat 解决了这个问题。

                    【讨论】:

                      【解决方案15】:

                      我只是想测试Union 在引用类型对象的重叠集合上如何与默认比较器一起工作。

                      我的对象是:

                      class MyInt
                      {
                          public int val;
                      
                          public override string ToString()
                          {
                              return val.ToString();
                          }
                      }
                      

                      我的测试代码是:

                      MyInt[] myInts1 = new MyInt[10];
                      MyInt[] myInts2 = new MyInt[10];
                      int overlapFrom = 4;
                      Console.WriteLine("overlapFrom: {0}", overlapFrom);
                      
                      Action<IEnumerable<MyInt>, string> printMyInts = (myInts, myIntsName) => Console.WriteLine("{2} ({0}): {1}", myInts.Count(), string.Join(" ", myInts), myIntsName);
                      
                      for (int i = 0; i < myInts1.Length; i++)
                          myInts1[i] = new MyInt { val = i };
                      printMyInts(myInts1, nameof(myInts1));
                      
                      int j = 0;
                      for (; j + overlapFrom < myInts1.Length; j++)
                          myInts2[j] = myInts1[j + overlapFrom];
                      for (; j < myInts2.Length; j++)
                          myInts2[j] = new MyInt { val = j + overlapFrom };
                      printMyInts(myInts2, nameof(myInts2));
                      
                      IEnumerable<MyInt> myUnion = myInts1.Union(myInts2);
                      printMyInts(myUnion, nameof(myUnion));
                      
                      for (int i = 0; i < myInts2.Length; i++)
                          myInts2[i].val += 10;
                      printMyInts(myInts2, nameof(myInts2));
                      printMyInts(myUnion, nameof(myUnion));
                      
                      for (int i = 0; i < myInts1.Length; i++)
                          myInts1[i].val = i;
                      printMyInts(myInts1, nameof(myInts1));
                      printMyInts(myUnion, nameof(myUnion));
                      

                      输出是:

                      overlapFrom: 4
                      myInts1 (10): 0 1 2 3 4 5 6 7 8 9
                      myInts2 (10): 4 5 6 7 8 9 10 11 12 13
                      myUnion (14): 0 1 2 3 4 5 6 7 8 9 10 11 12 13
                      myInts2 (10): 14 15 16 17 18 19 20 21 22 23
                      myUnion (14): 0 1 2 3 14 15 16 17 18 19 20 21 22 23
                      myInts1 (10): 0 1 2 3 4 5 6 7 8 9
                      myUnion (14): 0 1 2 3 4 5 6 7 8 9 20 21 22 23
                      

                      所以,一切正常。

                      【讨论】:

                        猜你喜欢
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 2020-09-11
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        相关资源
                        最近更新 更多