我有一系列物品。一个项目可以有另一个项目,另一个项目可以有另一个项目。等等。
我不知道嵌套项目可以有多少级别的项目。嵌套项的级别可以在运行时定义。
class Person
{
Person person;
public Person(Person _nestedPerson)
{
person = _nestedPerson;
}
public bool IsSelectedPerson { get; set; }
public string Name { get; set; }
}
以及如何嵌套项目(Person
):
IList<Person> list = new List<Person>();
for (int startIndex = 0; startIndex < 5; startIndex++)
{
list.Add(new Person(new Person(new Person(new Person(null) { Name="Bill",
IsSelectedPerson=true})) { Name = "Jessy", IsSelectedPerson = false })
{ Name = "Bond", IsSelectedPerson =true});//3 nested persons
list.Add(new Person(new Person(null) { Name = "Kendell",
IsSelectedPerson = true }) { Name="Rosy", IsSelectedPerson=true});//2 nested persons
//The next time it can be just one person without nested item(person). I do not know how many items(persons) will be nested
//list.Add(new Person(null) { Name="Rosy", IsSelectedPerson=true});
}
我的目标是采取所有对象(没有重复)Person
的人IsSelectedPerson=true
}
我玩过Select()
var ee = list.Select(x=>x.IsSelectedFacet==true);//comparison should be done here
但它不是我想要的,只需要bool
个值。
更新
我的预期结果应该是Person
一个具有唯一名称的对象。无论有多少具有相同名称的对象。我想只拿一个对象。很抱歉误导。它应该是这样的:
答案 0 :(得分:4)
您可以创建一个帮助方法来解包所有嵌套对象
IEnumerable<Person> UnwrapPerson(Person p)
{
List<Person> list = new List<Person>();
list.Add(p);
if (p.person != null)
list.AddRange(UnwrapPerson(p.person));
return list;
}
或者,如果Person
类只有一个嵌套对象(Person person;
),则可以使用yield
构造而不是递归
static IEnumerable<Person> UnwrapPerson(Person p)
{
yield return p;
while (p.person != null)
{
p = p.person;
yield return p;
}
}
为了删除所有重复的人,例如使用相同的名称,您应该实施IEqualityComparer<Person>
,然后使用Distinct
方法。
class Comparer : IEqualityComparer<Person>
{
public bool Equals(Person x, Person y)
{
return string.Equals(x.Name, y.Name);
}
public int GetHashCode(Person obj)
{
string name = obj.Name;
int hash = 7;
for (int i = 0; i < name.Length; i++)
{
hash = hash * 31 + name[i];
}
return hash;
}
}
所以最终查询应该类似于:
list.SelectMany(p => UnwrapPerson(p))
.Where(x => x.IsSelectedPerson == true)
.Distinct(new Comparer())
答案 1 :(得分:3)
这是另一种产生项目列表的方法:
IEnumerable<Person> GetIsSelectedPerson(Person p)
{
Person temp = p;
while (temp != null)
{
if (temp.IsSelectedPerson)
{
yield return temp;
}
temp = temp.person;
}
}
<强>用法:强>
IEnumberable<Person> Result = GetIsSelectedPerson(rootPerson)
答案 2 :(得分:1)
我会使用某种访问模式和递归来访问所有嵌套的Persons
:
class Person
{
public static List<Person> selectedPersons;
Person person;
public Person(Person _nestedPerson)
{
if(selectedPersons == null)
selectedPersons = new List<Person>();
person = _nestedPerson;
}
public bool IsSelectedPerson { get; set; }
public string Name { get; set; }
public void Visit()
{
if(this.IsSelectedPerson)
selectedPersons.Add(this);
if(this.person != null)
this.person.Visit();
}
}
答案 3 :(得分:1)
这样做可以使人们变得平坦,
Func<Person, IEnumerable<Person>> flattener = null;
flattener = p => new[] { p }
.Concat(
p.person == null
? Enumerable.Empty<Person>()
: (new [] { p.Person }).SelectMany(child => flattener(child)));
所以你可以这样做,
flattener(person).Where(p => p.IsSelectedPerson);
在您发表评论后,您可能想要的是,
flattener(person)
.Where(p => p.IsSelectedPerson)
.Select(p => p.Name)
.Distinct();
答案 4 :(得分:1)
由于您不知道链中的人员级别,最好是使用递归。两个简单的解决方案(假设您在Person类上添加方法)
创建一个接收列表的方法,以便在递归调用中填写它: 列表completeList = new List(); 列表[0] .GetCompleteList(completeList); 列表[1] .GetCompleteList(completeList);
public void GetCompleteList(List<Person> personsList)
{
personsList.Add(this);
if (person != null)
{
person.GetCompleteList(personsList);
}
}
相同,没有参数
List<Person> completeList = new List<Person>();
completeList.AddRange(list[0].GetCompleteList());
completeList.AddRange(list[1].GetCompleteList());
// Another way: with linq
var myPersons list.SelectMany(m => m.GetCompleteList());
public List<Person> GetCompleteList()
{
List<Person> returnList = new List<Person>();
returnList.Add(this);
if (person != null)
{
returnList.AddRange(person.GetCompleteList());
}
return returnList;
}