Reputation: 159
I want the output like
Test Genre1/
Test Genre2/
Test Genre3/Test genre1 //(Bcoz id 1 as Test Genre1)
Test Genre4/Test genre2 //(Bcoz id 2 as Test Genre2)
Test genre1/Test Test genre3/Genre5 //(Bcoz id 3 as Test Genre3)
It should be combination of the id
and parent id
in Linq
.
Any help will be appreciated...
Upvotes: 3
Views: 110
Reputation: 505
Create a recursive function and use that function in your linq. something like this.
//Recursive method
private static string GetParentPath( IEnumerable<Item> items , Item item )
{
if (item.ParentId.HasValue)
{
return GetParentPath(items, items.First(i => i.Id == item.ParentId)) + "/" + item.GenreName;
}
return item.GenreName;
}
var items = new Item[]
{
new Item {Id = 1, GenreName = "Test Genre 1", ParentId = null},
new Item {Id = 2, GenreName = "Test Genre 2", ParentId = null},
new Item {Id = 3, GenreName = "Test Genre 3", ParentId = 1},
new Item {Id = 4, GenreName = "Test Genre 4", ParentId = 2},
new Item {Id = 5, GenreName = "Test Genre 5", ParentId = 3}
};
// Linq query
var result = from child in items
select new { Path = GetParentPath(items, child) };
//Class used in example
public class Item
{
public int Id { get; set; }
public string GenreName { get; set; }
public int? ParentId { get; set; }
}
Upvotes: 0
Reputation: 6463
You can try a recursive method returning IEnumerable
defined on the entity class:
public class Genre
{
public int Id { get; set; }
public string Name { get; set; }
public int? ParentId { get; set; }
public IEnumerable<Genre> GetSelfAndAncestors(IEnumerable<Genre> items)
{
yield return this;
if (ParentId.HasValue)
{
var parent = items.First(x => x.Id == ParentId.Value);
foreach (var ancestor in parent.GetSelfAndAncestors(items))
{
yield return ancestor;
}
}
}
}
Usage:
var genres = new[]
{
new Genre {Id = 1, Name = "Test Genre 1", ParentId = null},
new Genre {Id = 2, Name = "Test Genre 2", ParentId = null},
new Genre {Id = 3, Name = "Test Genre 3", ParentId = 1},
new Genre {Id = 4, Name = "Test Genre 4", ParentId = 2},
new Genre {Id = 5, Name = "Test Genre 5", ParentId = 3}
};
foreach (var genre in genres)
{
var path = genre.GetSelfAndAncestors(genres);
Console.WriteLine(String.Join("/", path.Select(x => x.Name)));
}
If the tree is deep, you might notice a significant performance hit comparing this implementation with a non-IEnumerable
one.
Upvotes: 1
Reputation: 136104
Given a method to be called recursively which
private static string SelectGenreName(IEnumerable<Genre> all, Genre g)
{
var s = g.Name + '/';
if(g.ParentId.HasValue){
s += SelectGenreName(all, all.Single(x => x.Id == g.ParentId.Value));
}
return s;
}
The code to get a sensible result* is quite straightforward:
* sensible result; Your last example was reversed from the previous 4. The above gives results as per your first four examples. ie Child/Parent/Grandparent
var genres = new[]
{
new Genre {Id = 1, Name = "Test Genre 1", ParentId = null},
new Genre {Id = 2, Name = "Test Genre 2", ParentId = null},
new Genre {Id = 3, Name = "Test Genre 3", ParentId = 1},
new Genre {Id = 4, Name = "Test Genre 4", ParentId = 2},
new Genre {Id = 5, Name = "Test Genre 5", ParentId = 3}
};
var result = genres.Select(g => SelectGenreName(genres,g));
foreach(var r in result)
Console.WriteLine(r);
Live example: http://rextester.com/MXQUH43732
Upvotes: 1