从列表中仅选择一种类型

时间:2013-07-09 14:36:02

标签: c# linq list

我有一个这样的课程

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,但只选择多个分组对象中的一个。

由于

4 个答案:

答案 0 :(得分:9)

这应该可以解决问题(似乎来自测试)。

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);

它基本上分为两部分,第一部分简单地获取所有根项。第二个按父类对它们进行分组,然后选择每个组中的第一个项目。如果您想进一步细化选择哪一个,可以调整这个。

附加说明:

作为生成问题确切输出的练习,以下内容可用于childItems:

var childItems = persons.Where(x=>x.parentId!=0)
    .GroupBy(x=>x.parentId)
    .Select(
        x=>x.OrderBy(y=>y.Id%3)
        .First()
);

这显然是一种从选项中进行选择的略微荒谬的方式,但确实展示了如何通过添加某种类型的排序标准来更改选择的项目。

答案 1 :(得分:5)

要从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()));

答案 2 :(得分:2)

假设您有一个AllPersons列表:

var parentsAdded = new HashSet<int>();

foreach(var person in AllPersons)
{
    if(person.parentId == 0 || parentsAdded.Add(person.parentId))
    {
       persons.Add(person);
    }

}

答案 3 :(得分:1)

最简单的方法是使用parentId == 0方法使用Concat首先使用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;
        }
    }
}

但是,它需要两次通过集合。我建议为此编写自己的Extension方法:

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; } } 的通用版本:

{{1}}