从列表中只选择一种类型
本文关键字:一种 类型 列表 选择 | 更新日期: 2023-09-27 18:21:36
我有一个类似的类
class Person {
private Id;
private parentId;
private Name;
}
我有一份名单,看起来像这样:
List<Person> persons = new List<Person>();
persons.Add(new Person{Id =1, Name = "Andy", parentId = 0});
persons.Add(new Person{Id =2, Name = "Sandy", parentId = 0});
persons.Add(new Person{Id =3, Name = "Carter", parentId = 9});
persons.Add(new Person{Id =4, Name = "Mark", parentId = 9});
persons.Add(new Person{Id =5, Name = "Martin", parentId = 99});
persons.Add(new Person{Id =6, Name = "Matt", parentId = 99});
我想要的是:
persons.Add(new Person{Id =1, Name = "Andy", parentId = 0});
persons.Add(new Person{Id =2, Name = "Sandy", parentId = 0});
persons.Add(new Person{Id =3, Name = "Carter", parentId = 9});
persons.Add(new Person{Id =6, Name = "Matt", parentId = 99});
我想保留parentId为0的所有人,但只从多个分组对象中选择一个。
感谢
这应该可以完成任务(从测试来看)。
var rootItems = persons.Where(x=>x.parentId==0);
var childItems = persons.Where(x=>x.parentId!=0).GroupBy(x=>x.parentId).Select(x=>x.First());
var requiredItems = rootItems.Concat(childItems);
它基本上分为两部分,第一部分简单地获取所有根项。第二个按parentId对它们进行分组,然后选择每个组中的第一个项目。如果你想进一步完善选择哪一个,可以对其进行调整。
附加说明:
作为产生问题确切输出的练习,以下内容可用于childItems:
var childItems = persons.Where(x=>x.parentId!=0)
.GroupBy(x=>x.parentId)
.Select(
x=>x.OrderBy(y=>y.Id%3)
.First()
);
这显然是一种从选项中进行选择的略显荒谬的方式,但它确实展示了如何通过添加某种排序标准来更改选择的项目。
要从parentId的每个分组中获得一个人,只需根据该值分组,然后从每个分组中选择第一个人。然后,您可以将其与父id为0的人连接起来。
var query = people.Where(p => p.parentId == 0)
.Concat(people.Where(p => p.parentId != 0)
.GroupBy(p => p.parentId)
.Select(group => group.First()));
假设您有一个AllPersons:列表
var parentsAdded = new HashSet<int>();
foreach(var person in AllPersons)
{
if(person.parentId == 0 || parentsAdded.Add(person.parentId))
{
persons.Add(person);
}
}
最简单的方法是对使用Concat
方法合并的组中的parentId == 0
和使用两个单独的查询。
var results = people.Where(x => x.parentId == 0)
.Concat(persons.Where(x => x.parentId != 0)
.GroupBy(x => x.parentId)
.Select(x => x.First()))
然而,它需要两次通过集合。我建议您编写自己的扩展方法:
public static class Enumerable
{
public static IEnumerable<Person> GetFirsts(this IEnumerable<Person> source)
{
var set = new HashSet<int>();
foreach (var person in source)
{
if (person.parentId == 0 || set.Add(person.parentId))
yield return person;
}
}
}
然后像这样使用:
var results = people.GetFirsts();
编辑
或GetFirsts
:的通用版本
public static IEnumerable<TSource> GetFirsts<TSource, TKey> (this IEnumerable<TSource> source,
Func<TSource, TKey> selector,
TKey zeroValue)
{
var set = new HashSet<TKey>();
foreach (var item in source)
{
if (selector(item).Equals(zeroValue) || set.Add(selector(item)))
yield return item;
}
}