Please find the table structure below:
Folderid parentFolderid Guid
1 0 1234
2 1 5678
3 2 9012
4 3 87697
5 7 4443
The requirement is if I pass folderId the function has to give me all the guids.
For example:If I pass 1 to the function, I should get first four Guids(parent and its children).
I have a function which returns all the guids as follows:
public List<Guid> Folders(int folderId)
{
// To get the folderids based on parentfolderid
var a = entity.Where(x => x.parentfolderId == folderId).FirstOrDefault();
return a;
}
I am able to get only up to one level of ids.
Is there any way to get parent, its children, grandchildren till the leaf?
If you are able to get that table to a class, check this out:
public class Entity
{
public int ID { get; set; }
public int ParentID { get; set; }
public string Name { get; set; }
public static List<Entity> GetTree(int ID, List<Entity> ListToSearch, bool First = true)
{
List<Entity> FilteredEntities = new List<Entity>();
FilteredEntities.AddRange(ListToSearch.Where<Entity>(x => x.ParentID == ID).ToList<Entity>());
List<Entity> Temp = new List<Entity>();
foreach (Entity current in FilteredEntities)
{
Temp.AddRange(GetTree(current.ID, ListToSearch, false));
}
FilteredEntities.AddRange(Temp);
if (First)
{
FilteredEntities.Add(ListToSearch.Where<Entity>(x => x.ID == ID).Single<Entity>());
}
return FilteredEntities;
}
}
Usage:
List<Entity> filteredEntities = Entity.GetTree(1, entities);
List<string> onlyTheNames = filteredEntities.Select<Entity, string>(x => x.Name).ToList<string>();
Regards
If you use this node class, you can write the code like this.
public class Folder
{
public int Id { get; set; }
public int? ParentId { get; set; }
public Guid SomeGuid { get; set; }
}
and and example of what possible is:
var list = new List<Folder>
{
new Folder {Id = 0, ParentId = null, SomeGuid = new Guid("0000b25b-8538-4b78-818a-9094507e0000") },
new Folder {Id = 1, ParentId = 0, SomeGuid = new Guid("1000b25b-8538-4b78-818a-9094507e0001") },
new Folder {Id = 2, ParentId = 1, SomeGuid = new Guid("2000b25b-8538-4b78-818a-9094507e0002") },
new Folder {Id = 3, ParentId = 1, SomeGuid = new Guid("3000b25b-8538-4b78-818a-9094507e0003") },
new Folder {Id = 4, ParentId = 2, SomeGuid = new Guid("4000b25b-8538-4b78-818a-9094507e0004") },
new Folder {Id = 5, ParentId = 3, SomeGuid = new Guid("5000b25b-8538-4b78-818a-9094507e0005") },
new Folder {Id = 6, ParentId = 0, SomeGuid = new Guid("6000b25b-8538-4b78-818a-9094507e0006") },
new Folder {Id = 7, ParentId = 4, SomeGuid = new Guid("7000b25b-8538-4b78-818a-9094507e0007") },
new Folder {Id = 8, ParentId = 3, SomeGuid = new Guid("8000b25b-8538-4b78-818a-9094507e0008") },
};
var rootNode = Node<Folder>.CreateTree(list, n => n.Id, n => n.ParentId).Single();
var firstChild = rootNode.Children.First(); // Id 1
var descendentsOfFirstChild = firstChild.Descendants; // All descendants of node 1
Related
I have 2 list
IEnumerable<int> Ids, IEnumerable<Guid> GuidIds
for sample data
IEnumerable<int> ids1 = new List<int>() { 1, 2, 4 };
IEnumerable<Guid> guidIds = new List<Guid>() { new Guid("F44D7A64-8BDE-41E1-810F-B24377AD7F94"), new Guid("F44D7A64-8BDE-41E1-810F-B24377AD7F96"), new Guid("F44D7A64-8BDE-41E1-810F-B24377AD7F97") };
and a class
public class ClassEnd
{
public int Id { get; set; }
public Guid GuidId { get; set; }
}
I want to merge into this by Linq query
IEnumerable<ClassEnd> mergeList = new List<ClassEnd>()
{
new ClassEnd() { Id = 1, CompanyId = new Guid("F44D7A64-8BDE-41E1-810F-B24377AD7F94") },
new ClassEnd() { Id = 2, CompanyId = new Guid("F44D7A64-8BDE-41E1-810F-B24377AD7F96") },
new ClassEnd() { Id = 3, CompanyId = new Guid("F44D7A64-8BDE-41E1-810F-B24377AD7F97") }
};
Could you please help me with how to merge like the above "mergeList" by using Linq?
If lists are of the same size - it can be easily achieved with Enumerable.Zip:
var classEnds = ids1
.Zip(guidIds, (i, guid) => new ClassEnd
{
Id = i,
GuidId = guid
})
.ToList();
CREATE TABLE [dbo].[Topic] (
[Id] SMALLINT NOT NULL,
[ParentId] SMALLINT NULL
);
I have a simple table (above) with a parent/child hierarchy. I'm using Entity Framework to extract the data. The number of rows is less than 100.
I want to get a list of descendant ID, consisting of the children, grandchildren and so on (possibly with the option of including the original root parent). As the table only contains a small number of rows, it's probably easier to extract all the data to a List<Topic> first and work on that, but I stand to be corrected.
The preferred output would be: Dictionary<int, List<int>>
Where the key would be the ID and the list would contain child/grandchild ID's
I've looked at tens and tens of solutions online but I can't find a solution that meets my needs. Can anyone help?
You could populate a dictionary with the ParentId->Id relations and use that to resolve sub-topics:
// prepare dictionary
var dictionary = new Dictionary<short, List<Topic>>();
// in real life this would get replaced by your database query
var topics = new List<Topic>
{
new Topic { Id = 1 },
new Topic { Id = 2, ParentId = 1 },
new Topic { Id = 3, ParentId = 1 },
new Topic { Id = 4, ParentId = 1 },
new Topic { Id = 5, ParentId = 1 },
new Topic { Id = 6, ParentId = 2 },
new Topic { Id = 7, ParentId = 2 },
new Topic { Id = 8, ParentId = 3 },
new Topic { Id = 9, ParentId = 4 },
new Topic { Id = 10, ParentId = 4 },
new Topic { Id = 11, ParentId = 8 },
new Topic { Id = 12, ParentId = 8 }
};
// populate dictionary with relations from DB
foreach(var topic in topics)
{
var key = topic.ParentId ?? -1;
if(!dictionary.ContainsKey(key))
{
dictionary.Add(key, new List<Topic>());
}
dictionary[key].Add(topic);
}
Now that you have the mappings available, you can write a simple recursive iterator method to resolve the descendants of a given id:
IEnumerable<short> GetDescendantIDs(short from)
{
if(dictionary.ContainsKey(from))
{
foreach(var topic in dictionary[from])
{
yield return topic.Id;
foreach(var child in GetDescendants(topic.Id))
yield return child;
}
}
}
// resolves to [1, 2, 6, 7, 3, 8, 11, 12, 4, 9, 10, 5]
var descendantsOfRoot = GetDescendantIDs(-1);
// resolves to [8, 11, 12]
var descendantsOfThree = GetDescendantIDs(3);
The Topic class used in the example above is just:
class Topic
{
internal short Id { get; set; }
internal short? ParentId { get; set; }
}
Consider that result has to be stored in tree:
public class TopicModel
{
public int Id { get; set; }
public int? ParentId{ get; set; }
public List<TopicModel> Children { get; set; };
}
Building tree:
// retrieveing from database
var plainResult = context.Topic
.Select(t => new TopicModel
{
Id = x.Id
ParentId = x.ParentId
})
.ToList();
var lookup = plainResult.Where(x => x.ParentId != null).ToLookup(x => x.ParentId);
foreach (c in plainResult)
{
if (lookup.Contains(c.Id))
{
c.Children = lookup[c.Id].ToList();
}
}
// here we have all root items with children intialized
var rootItems = plainResult.Where(x => x.ParentId == null).ToList();
And searching for children:
public static IEnumerable<TopicModel> GetAllChildren(TopicModel model)
{
if (model.Children != null)
{
foreach (var c in model.Children)
{
yield return c;
foreach (sc in GetAllChildren(c))
yield return sc;
}
}
}
i have a method GetChild(id) that return the children with respect to id of parent passed as a parameter
those children can also have their own children to any level
if i want to create a JSON which represent the entire hierarchy of child and parent then how should i proceed?
public ActionResult GetChild(long id)
{
Dal objDal = new Dal();
var res = objDal.db.ChildGet(id).ToList();
return Json(res, JsonRequestBehavior.AllowGet);
}
this is justfor first level
how can i use this GetChild(id) method recursively?
any kind of help will be appreciated
public class Comment
{
public int Id { get; set; }
public int ParentId { get; set; }
public string Text { get; set; }
public List<Comment> Children { get; set; }
}
public JsonResult Test()
{
List<Comment> categories = new List<Comment>()
{
new Comment () { Id = 1, Text = "Yabancı Dil", ParentId = 0},
new Comment() { Id = 2, Text = "İngilizce", ParentId = 1 },
new Comment() { Id = 3, Text = "YDS", ParentId = 2 },
new Comment() { Id = 4, Text = "TOEFL", ParentId = 2 },
new Comment() { Id = 5, Text = "YDS Seviye1", ParentId = 3 },
new Comment() { Id = 6, Text = "TOEFL Seviye1", ParentId = 4 }
};
List<Comment> hierarchy = new List<Comment>();
hierarchy = categories
.Where(c => c.Id == 2)
.Select(c => new Comment()
{
Id = c.Id,
Text = c.Text,
ParentId = c.ParentId,
Children = GetChildren(categories, c.Id)
})
.ToList();
List<Comment> list = new List<Comment>();
List<string> list2 = new List<string>();
if (hierarchy != null)
{
liste.AddRange(hierarchy);
}
return Json(liste, JsonRequestBehavior.AllowGet);
}
public static List<Comment> GetChildren(List<Comment> comments, int parentId)
{
hAbDbContext db = new hAbDbContext();
return comments
.Where(c => c.ParentId == parentId)
.Select(c => new Comment()
{
Id = c.Id,
Text = c.Text,
ParentId = c.ParentId,
Children = GetChildren(comments, c.Id)
})
.ToList();
}
I'm using SQL Server and Entity Framework. On my database I have the following data:
ID | Name | ParentID
1 | Fire | null
2 | Fire2 | 1
3 | Fire3 | 2
4 | Blast | 2
5 | Water | null
6 | Water2 | 5
7 | WaterX | 5
I won't have massive data, so retrieving everything at once from the database is perfectly acceptable.
I want to retrieve this data and display on screen as a "tree".
Fire
Fire2
Fire3 Blast
Water
Water2 WaterX
How should I do this? Should I create some sort of recursion to render it? Should I somehow convert the list to an IGrouping?
I'm having trouble converting the flat list into something that I can render hierarchically on the screen, how could I do that?
This is the easiest way I know:
var things = new []
{
new { Id = 1, Name = "Fire", ParentId = (int?)null },
new { Id = 2, Name = "Fire2", ParentId = (int?)1 },
new { Id = 3, Name = "Fire3", ParentId = (int?)2 },
new { Id = 4, Name = "Blast", ParentId = (int?)2 },
new { Id = 5, Name = "Water", ParentId = (int?)null },
new { Id = 6, Name = "Water2", ParentId = (int?)5 },
new { Id = 7, Name = "Waterx", ParentId = (int?)5 }
};
var tree = things.ToLookup(x => x.ParentId, x => new { x.Id, x.Name });
The tree looks like this:
That should be fairly easy to render now.
If you can add another property to your class that has the child items like this:
public class Thing
{
public Thing()
{
Things = new List<Thing>();
}
public int Id { get; set; }
public string Name { get; set; }
public int? ParentId { get; set; }
public List<Thing> Things { get; set; }
}
Then you can easily group the items to their parents like this:
var things = new List<Thing>
{
new Thing { Id = 1, Name = "Fire", ParentId = null },
new Thing { Id = 2, Name = "Fire2", ParentId = 1 },
new Thing { Id = 3, Name = "Fire3", ParentId = 2 },
new Thing { Id = 4, Name = "Blast", ParentId = 2},
new Thing { Id = 5, Name = "Water", ParentId = null },
new Thing { Id = 6, Name = "Water2", ParentId = 5 },
new Thing { Id = 7, Name = "Waterx", ParentId = 6 }
};
var groupedThings = new List<Thing>();
foreach (var thing in things)
{
if (thing.ParentId != null)
{
things.First(t => t.Id == thing.ParentId).Things.Add(thing);
}
else
{
groupedThings.Add(thing);
}
}
groupedThings.Dump();
I want to remove items from a list of entities, when there is a concidence from a list (id). I have written this code, but I am guessing there is a better way to do it, and improve performance.
Here is my code:
List<int> toRemove; //includes the ids of the entities to be removed
if (people.Count > 1)
people.RemoveAll(x => people.Any(y => y != x && toRemove.Contains(x.ID)));
else
people.RemoveAll(x => toRemove.Contains(x.ID));
Given a list of people, for example:
var people = new List<Person>
{
new Person { ID = 1, Name = "Fred1" },
new Person { ID = 2, Name = "Fred2" },
new Person { ID = 3, Name = "Fred3" },
new Person { ID = 4, Name = "Fred4" },
new Person { ID = 5, Name = "Fred5" },
new Person { ID = 6, Name = "Fred6" },
new Person { ID = 7, Name = "Fred7" },
new Person { ID = 8, Name = "Fred8" },
new Person { ID = 9, Name = "Fred9" },
new Person { ID = 10, Name = "Fred10" }
};
And a list of IDs to remove:
List<int> toRemove = new List<int> { 3, 4, 5 };
You can remove the unwanted entries like this:
people = people.Where(p => !toRemove.Contains(p.ID)).ToList();
Oh, and for completeness, here's a Person class to complete the example!
public class Person
{
public int ID { get; set; }
public string Name { get; set; }
}
And to show it working:
https://ideone.com/ERP3rk