У меня следующая ситуация
class Person
{
string Name;
int Value;
int Change;
}
List<Person> list1;
List<Person> list2;
Мне нужно объединить 2 списка в новый List<Person>
на тот случай, если это будет тот же человек, у которого объединенная запись будет иметь это имя, значение человека в list2, изменение будет значением list2 - значением list1. Изменение равно 0, если нет дубликатов
Ответы:
Это легко сделать с помощью метода расширения Linq Union. Например:
Это вернет список, в котором два списка объединены и двойники удалены. Если вы не укажете компаратор в методе расширения Union, как в моем примере, он будет использовать методы Equals и GetHashCode по умолчанию в вашем классе Person. Если вы, например, хотите сравнить людей, сравнивая их свойство Name, вы должны переопределить эти методы, чтобы выполнить сравнение самостоятельно. Проверьте следующий пример кода, чтобы сделать это. Вы должны добавить этот код в свой класс Person.
Если вы не хотите устанавливать метод Equals по умолчанию в своем классе Person, чтобы всегда использовать имя для сравнения двух объектов, вы также можете написать класс сравнения, который использует интерфейс IEqualityComparer. Затем вы можете предоставить этот компаратор в качестве второго параметра в методе объединения Linq. Дополнительную информацию о том, как написать такой метод сравнения, можно найти по адресу http://msdn.microsoft.com/en-us/library/system.collections.iequalitycomparer.aspx.
источник
Union
сIntersect
?Concat
то, что не объединяет дубликатыЯ заметил, что этот вопрос не был отмечен как ответ через 2 года - я думаю, что самый близкий ответ - Ричардс, но это может быть упрощено довольно много к этому:
Хотя это не будет ошибкой в случае, если у вас есть повторяющиеся имена в любом наборе.
В некоторых других ответах предлагается использовать объединение - это определенно не тот путь, поскольку он даст вам только отдельный список без объединения.
источник
Почему вы не просто используете
Concat
?Concat является частью linq и более эффективен, чем
AddRange()
в твоем случае:
источник
Actually, due to deferred execution, using Concat would likely be faster because it avoids object allocation - Concat doesn't copy anything, it just creates links between the lists so when enumerating and you reach the end of one it transparently takes you to the start of the next!
Это моя точка зрения.Это Линк
Это Нормалы (AddRange)
Это Нормалы (Foreach)
Это Нормалы (Foreach-Dublice)
источник
Для этого есть несколько частей, при условии, что каждый список не содержит дубликатов, Name является уникальным идентификатором, и ни один список не упорядочен.
Сначала создайте метод расширения append, чтобы получить единый список:
Таким образом можно получить единый список:
Тогда группа по имени
Затем можно обрабатывать каждую группу с помощником для обработки по одной группе за раз
Который может применяться к каждому элементу
grouped
:(Предупреждение: не проверено.)
источник
Append
- почти точная копия оригинальногоConcat
.Enumerable.Concat
и, таким образом, заново его реализовывал.Вам нужно что-то вроде полного внешнего соединения. System.Linq.Enumerable не имеет метода, который реализует полное внешнее соединение, поэтому мы должны сделать это сами.
источник
Работает ли следующий код для вашей проблемы? Я использовал foreach с небольшим количеством linq внутри для объединения списков и предполагал, что люди равны, если их имена совпадают, и, кажется, при запуске выдает ожидаемые значения. Resharper не предлагает никаких предложений по конвертации foreach в linq, так что это, вероятно, так же хорошо, как это получится.
источник
источник