#c#
Вопрос:
Я пытаюсь найти различные имена a List<Person>
на основе Name
свойства. Для каждого отдельного имени я хочу создать новый объект с тем же свойством name, а все остальные свойства равны нулю. Как мне сделать это эффективно?
Класс Person .
public class Person
{
public string Name { get; set; }
public string Country { get; set; }
}
Program.cs
List<Person> personList = new List<Person>();
var p1 = new Person()
{
Name = "John",
Country = "USA"
};
var p2 = new Person()
{
Name = "John",
Country = "China"
};
var p3 = new Person()
{
Name = "Bob",
Country = "Italy"
};
var p4 = new Person()
{
Name = "Bob",
Country = "Brazil"
};
var p5 = new Person()
{
Name = "Bob",
Country = "Canada"
};
personList.Add(p1);
personList.Add(p2);
personList.Add(p3);
personList.Add(p4);
personList.Add(p5);
Цель состоит в том, чтобы добавить еще одного «Джона» и еще одного «Боба» в тот же список (потому что у них разные имена) со свойствами страны в качестве нулевой строки.
Комментарии:
1.
personList.GroupBy(x => x.Name).Select(x => new Person{ Name = x.Key }).ToArray()
2. @MetroSmurf не работает!
3. Конечно, это так: dotnetfiddle.net/YY7kSS
4. Добавлен ответ с возможностью добавления различных значений в существующий список.
5. Пожалуйста, откройте новый вопрос, поскольку это совершенно другой вопрос. Однако сначала выполните поиск ответа SO, поскольку его задавали и отвечали несколько раз.
Ответ №1:
Использование запроса Linq упростит поиск всех отдельных Name
значений:
// first use .GroupBy to group everything by the Name property
// and then select a new Person for each grouping of Name
Person[] unique = personList.GroupBy(x => x.Name)
.Select(x => new Person{Name = x.Key})
.ToArray();
После создания новой коллекции; добавьте их в существующую коллекцию:
personList.AddRange(unique);
Редактировать для использования с .Disinct
В качестве альтернативы, вы можете получить различные значения имен из метода Linq .Distinct()
вместо использования .GroupBy()
метода, но вам нужно выбрать .Name
свойство, чтобы получить OOB distinct comparer:
Person[] unique = personList.Select(x => x.Name)
.Distinct()
.Select(x => new Person{Name = x})
.ToArray();
personList.AddRange(unique);
Использование Distinct требует либо использования встроенного IEqualityComparer
, либо предоставления пользовательского IEqualityComparer
в перегрузке. Простая передача самого объекта недопустима, если объект не реализует IEqualityComparer
. В этом случае проще либо выбрать Name
свойство и вызвать .Distinct
, которое будет использовать встроенное IEqualityComparer
, либо использовать .GroupBy
метод, как в первом примере.
Ответ №2:
Используйте метод Distinct от linq (https://docs.microsoft.com/en-us/dotnet/api/system.linq.enumerable.distinct?view=net-5.0 ):
public class Person
{
public string Name { get; set; }
public string Country { get; set; }
}
// Program.cs
List<Person> personList = new List<Person> ();
var p1 = new Person ()
{
Name = "John",
Country = "USA"
};
var p2 = new Person ()
{
Name = "John",
Country = "China"
};
var p3 = new Person ()
{
Name = "Bob",
Country = "Italy"
};
var p4 = new Person ()
{
Name = "Bob",
Country = "Brazil"
};
var p5 = new Person ()
{
Name = "Bob",
Country = "Canada"
};
personList.Add(p1);
personList.Add (p2);
personList.Add (p3);
personList.Add (p4);
personList.Add (p5);
var personsWithDistinctNameInPersonList = personList.Select(p => p.Name).Distinct()
.Select(n => new Person {
Name = n,
}).ToList();
personList.AddRange(personsWithDistinctNameInPersonList);
Комментарии:
1. Это приводит к сбою как в методе Distinct (в качестве средства сравнения ничего не определено), так и затем завершится ошибкой с InvalidOperationException при попытке изменить коллекцию во время перечисления.
2. Поскольку я сначала выбираю только свойство name каждого пользователя, linq должен иметь возможность использовать встроенное по умолчанию средство сравнения строк просто отлично. В предоставленном фрагменте кода перечисление в списке пользователей не выполняется при вызове метода AddRange.
3. Я не видел
.Select
раньше. Итак, это работает, но InvalidOperationEx все равно будет возникать, потому что вам нужно материализовать запрос; как написано, он еще не материализован, пока вы не попытаетесь добавить его в ту же коллекцию.4.
personsWithDistinctNameInPersonList
не вычисляется до.ToArray()
тех пор, пока не будет вызвана операция, такая как.AddRange()
или . Это называется отложенной оценкой. Как написано в настоящее время, он завершается с ошибкой. Точка. Вам нужно вызвать.ToArray()
, чтобы ваш пример скомпилировался.5. Я добавил ToList()