Объединение двух списков вместе
Если у меня есть два списка строки типа (или любого другого типа), что такое быстрый способ объединения двух списков?
Порядок должен оставаться неизменным. Дубликаты должны быть удалены (хотя каждый элемент в обоих ссылках уникален). Я не нашел многого в этом, когда googling и не хотел реализовывать какие-либо .NET-интерфейсы для скорости доставки.
Ответы
Ответ 1
Вы можете попробовать:
List<string> a = new List<string>();
List<string> b = new List<string>();
a.AddRange(b);
Страница MSDN для AddRange
Это сохраняет порядок списков, но не удаляет дубликаты, которые Union
.
Это список изменений a
. Если вы хотите сохранить исходные списки, вы должны использовать Concat
(как указано в других ответах):
var newList = a.Concat(b);
Это возвращает IEnumerable
, если a
не является нулевым.
Ответ 2
Способ с наименьшими затратами на пространство - использовать метод расширения Concat.
var combined = list1.Concat(list2);
Создает экземпляр IEnumerable<T>
, который будет перечислять элементы list1 и list2 в этом порядке.
Ответ 3
Метод Union может удовлетворить ваши потребности. Вы не указали, был ли порядок или дубликаты важными.
Возьмите два IEnumerables и выполните объединение, как показано здесь:
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.
С помощью "Союза" вы также можете указать компаратор, который может использоваться для указания того, должен ли элемент объединяться или нет.
Вот так:
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
Ответ 5
Если в обоих списках есть какой-либо элемент (ы), вы можете использовать
var all = list1.Concat(list2).Concat(list3) ... Concat(listN).Distinct().ToList();
Ответ 6
targetList = list1.Concat(list2).ToList();
Он работает отлично, я так думаю. Как было сказано ранее, Concat возвращает новую последовательность и при преобразовании результата в List, он отлично выполняет работу. Неявные преобразования могут иногда не срабатывать при использовании метода AddRange.
Ответ 7
Пока они одного типа, это очень просто с AddRange:
list2.AddRange(list1);
Ответ 8
метод AddRange
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 }
Ответ 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
Смотрите ссылку
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
*/
Ответ 13
Я просто хотел проверить, как 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
Итак, все работает нормально.