I have a collection of items. The one item can have another item, and another item can have another item. So on.
I do not know how many levels of nested items can have item. The level of nested items can be defined at run-time.
class Person
{
Person person;
public Person(Person _nestedPerson)
{
person = _nestedPerson;
}
public bool IsSelectedPerson { get; set; }
public string Name { get; set; }
}
and how items(Person
) can be nested:
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});
}
My goal is to take ALL objects(without duplicates) of persons(Person
) who IsSelectedPerson=true
?
I've played with Select()
var ee = list.Select(x=>x.IsSelectedFacet==true);//comparison should be done here
but it is not what I want, it just takes bool
values.
Update:
My expected result should be have one object of Person
with unique name. No matter how many there are objects with the same name. I would like to take just one object. Sorry for misleading. It should be look like this:
You can make a helper method to unwrap all nested objects
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;
}
Or if Person
class has only one nested object (Person person;
) you can use a yield
construction instead of the recursion
static IEnumerable<Person> UnwrapPerson(Person p)
{
yield return p;
while (p.person != null)
{
p = p.person;
yield return p;
}
}
In order to remove all duplicate persons, for example with the same name, you should implement IEqualityComparer<Person>
and then use Distinct
method.
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;
}
}
So final query should be similar to:
list.SelectMany(p => UnwrapPerson(p))
.Where(x => x.IsSelectedPerson == true)
.Distinct(new Comparer())