I have the class:
class Node
{
public string Name;
public string Address;
public int Id;
public List<Node> Children = new List<Node>;
public Node Parent;
}
To represent a node in a tree.
Now I will like to remove the duplicate nodes from a tree. Take for instance the tree:
Note: green Foo != purple Foo
What algorithm will enable me to remove the duplicates from the tree in order to end up with:
-------------------------------------------
In order to determine that the green Foo is not equal (!=) to purple Foo I guess I need to have another property that stores the height of the node or some other property that will enable me to enable me to compare nodes. This is the property I think I need (CompareId):
class Node
{
public string Name;
public string Address;
public int Id;
public List<Node> Children = new List<Node>();
public Node Parent;
public string CompareId // <----------------- Property I need to compare
{
get
{
var temp = this.Name + this.Address + this.Id;
if (this.Parent == null)
return temp;
else
return temp + this.Parent.CompareId;
}
}
}
If you wish to create the same tree I have here is the code:
Node root = new Node() { Name = "Root", Id = 12, Address = "0x0A1F12" };
Node tom1 = new Node() { Name = "Tom", Id = 15, Address = "0x0F1A17", Parent=root };
root.Children.Add(tom1);
Node tom2 = new Node() { Name = "Tom", Id = 15, Address = "0x0F1A17", Parent = root };
root.Children.Add(tom2);
Node foo = new Node() { Name = "Foo", Id = 99, Address = "0x4C0012", Parent=root };
root.Children.Add(foo);
Node foo1 = new Node() { Name = "Foo", Id = 99, Address = "0x4C0012", Parent = tom1 };
tom1.Children.Add(foo1);
Node foo2 = new Node() { Name = "Foo", Id = 99, Address = "0x4C0012", Parent = tom1 };
tom1.Children.Add(foo2);
Node foo3 = new Node() { Name = "Foo", Id = 99, Address = "0x4C0012", Parent = tom2};
tom2.Children.Add(foo3);
Node foo4 = new Node() { Name = "Foo", Id = 99, Address = "0x4C0012", Parent = tom2};
tom2.Children.Add(foo4);
Node joe1 = new Node() { Name = "Joe", Id = 99, Address = "0x605C2C", Parent = foo };
foo.Children.Add(joe1);
Node joe2 = new Node() { Name = "Joe", Id = 99, Address = "0x605C2C", Parent = foo };
foo.Children.Add(joe2);
Please, check this out:
public class Node
{
public string Name;
public string Address;
public int Id;
public List<Node> Children;
public Node Parent;
public Node()
{
this.Children = new List<Node>();
}
public string CompareId
{
get
{
var temp = string.Concat(this.Name, this.Address, this.Id);
if (this.Parent == null)
return temp;
else
return string.Concat(temp, this.Parent.CompareId);
}
}
public override bool Equals(object OtherNode)
{
if (OtherNode is Node)
return this.CompareId.Equals(((Node)OtherNode).CompareId);
else
return false;
}
public static Node RemoveDuplicatesFromTree(Node RootNode)
{
if (RootNode.Children.Count > 0)
{
List<Node> OldChildrenList = new List<Node>();
OldChildrenList.AddRange(RootNode.Children);
foreach (Node CurrentChild in OldChildrenList)
{
if (RootNode.Children.Any<Node>(x => x.Equals(CurrentChild)))
{
List<Node> Duplicates = RootNode.Children.Where(x => x.Equals(CurrentChild)).ToList<Node>();
Duplicates.ForEach(x =>
{
CurrentChild.Children = CurrentChild.Children.Union<Node>(x.Children).ToList<Node>();
RootNode.Children.Remove(x);
});
RootNode.Children.Add(CurrentChild);
}
Node.RemoveDuplicatesFromTree(CurrentChild);
}
}
return RootNode;
}
}
It may be needless to say, still. Usage:
Node.RemoveDuplicatesFromTree(root);
private void RemoveDuplicatesFromTree(Node root)
{
List<Node> nodesToBeremoved = new List<Node>();
root.Children.ForEach(p =>
{
if (!nodesToBeremoved.Contains(p))
{
nodesToBeremoved.AddRange(root.Children.Where(q => q.Name == p.Name && q != p));
}
});
for (int i = 0; i < nodesToBeremoved.Count; i++)
{
root.Children.Remove(nodesToBeremoved[i]);
}
if (root.Children != null && root.Children.Count > 0)
{
root.Children.ForEach(t => this.RemoveDuplicatesFromTree(t));
}
}
Just pass the root to this recursive function; it will trim all duplicates in the same level. You do not need to create a compare Id.
static void RemoveDuplicates(ref Node root)
{
Dictionary<string, Node> nonDuplicates = new Dictionary<string, Node>();
Action<Node> traverseTree = null;
traverseTree = (x) =>
{
var compareId = x.CompareId;
if (nonDuplicates.ContainsKey(compareId)) // if there is a duplicate
{
x.Parent.Children.Remove(x); // remove node
}
else
{
nonDuplicates.Add(compareId, x);
}
// cannot use foreach loop because removing a node will result in exception
// keep traversing the tree
for (var i = x.Children.Count - 1; i >= 0; i--)
traverseTree(x.Children[i]);
};
traverseTree(root);
}
Related
I have a collection of a Parent class. Parent class has an ID property and some other class property. So, I would like to fetch those child property values on the basis of the Parent ID. I am able to fetch an item of the collection but I need a single value from that item. Below is my code:
public class Parent
{
public int Id { get; set; }
public Child MyChild { get; set; }
}
public class Child
{
public string abc { get; set; }
public string xyz { get; set; }
}
class Program
{
static void Main(string[] args)
{
var d = new List<Parent>();
d.Add(new Parent
{
Id = 1,
MyChild = new Child()
{
xyz = "XYZ one",
abc = "ABC one"
}
});
d.Add(new Parent
{
Id = 2,
MyChild = new Child()
{
xyz = "XYZ two",
abc = "ABC two"
}
});
for (int i = 1; i < 2; i++)
{
var xyzValueOfParentIdOneValue = d.SingleOrDefault(x => x.Id = 1) // Here, I want to get XYZ property value of Parent ID 1.
}
}
}
You could use this
var xyzValueOfParentIdOneValue = d.SingleOrDefault(x => x.Id == 1)
?.MyChild
?.xyz;
if (xyzValueOfParentIdOneValue != null)
{
......
}
Or
var foundItem = d.SingleOrDefault(x => x.Id == 1);
if (foundItem != null && foundItem.MyChild != null)
{
var xyzValueOfParentIdOneValue = foundItem.MyChild.xyz;
}
These two above codes are completely similar.
I think you just want to access the MyChild property of the Parent, like:
var parent = d.SingleOrDefault(x => x.Id == 1);
var xyz = parent.MyChild.xyz;
Since you want to return a default value "0" if the Parent Id doesn't exist, you could use
var xyzValueOfParentIdOneValue = d.SingleOrDefault(x => x.Id == idToSearch)?
.MyChild?
.xyz ?? "0";
I have a small hierarchy. Example:
entity:
public class MyClass
{
public int ID { get; set; }
public string Name { get; set; }
public int ParentID { get; set; }
}
My hierarchy data look like:
Id = 1 Name = Item1 ParentId = NULL
Id = 2 Name = Item2 ParentId = 1
Id = 3 Name = Item3 ParentId = 2
Id = 4 Name = Item4 ParentId = 2
Id = 5 Name = Item5 ParentId = 3
The problem is I need to sort it that child nodes must be after its immediate parent. The example bellow must look like
Id = 1 Name = Item1 ParentId = NULL
Id = 2 Name = Item2 ParentId = 1
Id = 3 Name = Item3 ParentId = 2
// the elements with parentID = 3
Id = 5 Name = Item5 ParentId = 3
//continue
Id = 4 Name = Item4 ParentId = 2
Any adwices?
Assuming you have a _list of MyClass objects, then sort it first on Name field, then on ParentId field, like shown below using LINQ:
_list.OrderBy(L=>L.Name).ThenBy(L=>L.ParentId);
Hope this may help.
Try this
I assume that 1st you want to order by parentid and in each parent you want to sort by id.
myClassList.OrderBy(parent=>parent.ParentId).ThenBy(parent=>parent.Id);
Try this recursive code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
MyClass.data = new List<MyClass>() {
new MyClass() { ID = 1, Name = "Item1", ParentID = null},
new MyClass() { ID = 2, Name = "Item2", ParentID = 1 },
new MyClass() { ID = 3, Name = "Item3", ParentID = 2 },
new MyClass() { ID = 4, Name = "Item4", ParentID = 2 },
new MyClass() { ID = 5, Name = "Item5", ParentID = 3 }
};
MyClass myClass = new MyClass();
myClass.GetData(null, 0);
Console.ReadLine();
}
}
public class MyClass
{
public static List<MyClass> data = null;
public int ID { get; set; }
public string Name { get; set; }
public int? ParentID { get; set; }
public void GetData(int? id, int level)
{
List<MyClass> children = data.Where(x => x.ParentID == id).ToList();
foreach (MyClass child in children)
{
Console.WriteLine(" {0} ID : {1}, Name : {2}, Parent ID : {3}", new string(' ',4 * level),child.ID, child.Name, child.ParentID);
GetData(child.ID, level + 1);
}
}
}
}
Here you have a way to do it. As you can see, I overrode the ToString method and added a few more cases.
public class MyClass
{
public int Id { get; set; }
public string Name { get; set; }
public int? ParentId { get; set; }
public override string ToString()
{
return string.Format("{0}: {1} - {2}", Id, Name, ParentId);
}
}
class Program
{
static void Main(string[] args)
{
List<MyClass> list = new List<MyClass>();
list.Add(new MyClass { Id = 1, Name = "Item1", ParentId = null });
list.Add(new MyClass { Id = 2, Name = "Item2", ParentId = 1 });
list.Add(new MyClass { Id = 3, Name = "Item3", ParentId = 2 });
list.Add(new MyClass { Id = 4, Name = "Item4", ParentId = 2 });
list.Add(new MyClass { Id = 5, Name = "Item5", ParentId = 3 });
list.Add(new MyClass { Id = 6, Name = "Item6", ParentId = 1 });
list.Add(new MyClass { Id = 7, Name = "Item7", ParentId = null });
list.Add(new MyClass { Id = 8, Name = "Item8", ParentId = 2 });
list.Add(new MyClass { Id = 9, Name = "Item9", ParentId = 6 });
list.Add(new MyClass { Id = 10, Name = "Item10", ParentId = 7 });
foreach(var item in list.Where(x => !x.ParentId.HasValue).OrderBy(x => x.Id))
ProcessItem(item, list, 0);
Console.ReadKey();
}
private static void ProcessItem(MyClass item, List<MyClass> list, int level)
{
Console.WriteLine("{0}{1}", new string(' ', level * 2), item.ToString());
foreach (var subitem in list.Where(x => x.ParentId == item.Id).OrderBy(x => x.Id))
ProcessItem(subitem, list, level + 1);
}
}
Would something like this work for you?
If you need an actual ordered list, try this:
foreach (var item in OrderList(list))
Console.WriteLine(item.ToString());
(...)
private static List<MyClass> OrderList(List<MyClass> list)
{
List<MyClass> orderedList = new List<MyClass>(list.Count());
foreach (var item in list.Where(x => !x.ParentId.HasValue).OrderBy(x => x.Id))
AddItem(item, list, orderedList);
return orderedList;
}
private static void AddItem(MyClass item, List<MyClass> list, List<MyClass> orderedList)
{
orderedList.Add(item);
foreach (var subitem in list.Where(x => x.ParentId == item.Id).OrderBy(x => x.Id))
AddItem(subitem, list, orderedList);
}
The following should do the trick (and show some better performance because we save the hierarchy in a lookup, instead of searching the IEnumerable on the fly):
public List<MyClass> SortHierarchically(IEnumerable<MyClass> myClasses)
{
if(myClasses == null)
return new List<MyClass>();
var myClassesByParentId = myClasses.ToLookup(mc => mc.ParentId);
var result = new List<MyClass>(myClasses.Count());
int? currentParentId = null;
MyClass currentItem = myClassesByParentId[currentParentId].Single();
result.Add(currentItem);
currentParentId = currentItem.Id;
if(myClassesByParentId.Contains(currentParentId))
result.AddRange(myClassesByParentId[currentParentId].SelectMany(mc => GetAllSortedChildren(mc, myClassesByParentId)));
return result;
}
public List<MyClass> GetAllSortedChildren(MyClass parent, ILookup<int?, MyClass> myClassesByParentId)
{
var result = new List<MyClass>() { parent };
if(myClassesByParentId.Contains(parent.Id))
retsult.AddRange(myClassesByParentId[parent.Id].SelectMany(mc => GetAllSortedChildren(mc, myClassesByParentId)));
return result;
}
It would be interesting to find a method of sorting this by standard LINQ, with some clever comparer or such.
One of the answers above works well. This is a generic version.
public static class SortingMethods
{
public static IList<T> OrderByHierarchical<T>(
this IEnumerable<T> items,
Func<T, string> getId,
Func<T, string> getParentId)
{
if (items == null)
return new List<T>();
var itemsByParentId = items.ToLookup(item => getParentId(item));
var result = new List<T>(items.Count());
var currentParentId = "";
var currentItem = itemsByParentId[currentParentId].Single();
result.Add(currentItem);
currentParentId = getId(currentItem);
if (itemsByParentId.Contains(currentParentId))
result.AddRange(itemsByParentId[currentParentId].SelectMany(item => GetAllSortedChildren(item, itemsByParentId, getId)));
return result;
}
private static IList<T> GetAllSortedChildren<T>(T parent, ILookup<string, T> itemsByParentId, Func<T, string> getId)
{
var result = new List<T>() { parent };
if (itemsByParentId.Contains(getId(parent)))
{
result.AddRange(itemsByParentId[getId(parent)].SelectMany(item => GetAllSortedChildren(item, itemsByParentId, getId)));
}
return result;
}
}
I have an input stream something like this:
John
Peter
Vanesa
Vanesa.New
Josh
Josh.New
Josh.New.Under
...
I need to Add Nodes to TreeView Someting like this:
+Customers
+John
+Peter
+Vanesa
+New
+Josh
+New
+Under
...
I have an idea to split every string with parameter '.', but i have a problem with dynamicly loaded nodes. Maybe i have to use some kind of foreach...
I have old database table "group" with records id and GroupName. The are filled with these strings. I need to create some kind of "address" like: John.Element or Vanesa.New.Element or Josh.New.Under.Element, where Element is record from other datatable. The DB connection is not the problem, the problem is the dynamicly fill the tree
For now i have done adding strings that don't contains '.':
reader = readGroups.ExecuteNonQuery();
while(reader.Read())
{
string[] buff = reader.GetValue(1).ToString().Split('.');
if (buff.Length == 1)
{
treeView1.Nodes[0].Nodes.Add(reader.GetValue(1));
}
else
{
//group contains '.'
}
}
EDIT:
I have one more problem. There is records like this: John, John.New, John.Old, John.Older, John.Oldest ... So when the AddNodes() method runs, the foreach in the end of the method clears John.New, John.Old, John.Older nodes, but they got to go into the treenode John. If you have some idea...
For winforms this is what you will need. I'm using recursion to add each child node inside each parent node. And I've made changes so that it will create a list of unique nodes before it starts adding any to the actual treeview
internal class TreeNodeHierachy
{
public int Level { get; set; }
public TreeNode Node { get; set; }
public Guid Id { get; set; }
public Guid ParentId { get; set; }
public string RootText { get; set; }
}
private List<TreeNodeHierachy> overAllNodeList;
private void AddNodes(IEnumerable<string> data)
{
overAllNodeList = new List<TreeNodeHierachy>();
foreach (var item in data)
{
var nodeList = new List<TreeNodeHierachy>();
var split = item.Split('.');
for (var i = 0; i < split.Count(); i++)
{
var guid = Guid.NewGuid();
var parent = i == 0 ? null : nodeList.First(n => n.Level == i - 1);
var root = i == 0 ? null : nodeList.First(n => n.Level == 0);
nodeList.Add(new TreeNodeHierachy
{
Level = i,
Node = new TreeNode(split[i]) { Tag = guid },
Id = guid,
ParentId = parent != null ? parent.Id : Guid.Empty,
RootText = root != null ? root.RootText : split[i]
});
}
// figure out dups here
if (!overAllNodeList.Any())
{
overAllNodeList.AddRange(nodeList);
}
else
{
nodeList = nodeList.OrderBy(x => x.Level).ToList();
for (var i = 0; i < nodeList.Count; i++)
{
var existingNode = overAllNodeList.FirstOrDefault(
n => n.Node.Text == nodeList[i].Node.Text && n.Level == nodeList[i].Level && n.RootText == nodeList[i].RootText);
if (existingNode != null && (i + 1) < nodeList.Count)
{
nodeList[i + 1].ParentId = existingNode.Id;
}
else
{
overAllNodeList.Add(nodeList[i]);
}
}
}
}
foreach (var treeNodeHierachy in overAllNodeList.Where(x => x.Level == 0))
{
treeView1.Nodes.Add(AddChildNodes(treeNodeHierachy));
}
}
private TreeNode AddChildNodes(TreeNodeHierachy node)
{
var treeNode = node.Node;
foreach (var treeNodeHierachy in overAllNodeList.Where(n => n.ParentId == node.Id))
{
treeNode.Nodes.Add(AddChildNodes(treeNodeHierachy));
}
return treeNode;
}
/// <summary>
/// Handles the Click event of the button1 control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
private void button1_Click(object sender, EventArgs e)
{
//SearchActiveDirectoryWithCriteria("(mailnickname=TM418)");
var test = new List<string>
{
"John",
"Peter",
"Vanesa",
"Vanesa.New",
"Josh",
"Josh.New",
"Josh.New.Under",
"Josh.Old"
};
AddNodes(test);
}
This will probably do mainly what you want, you'll also need some xaml with a TreeView called treeView:
public TreeViewItem root;
public MainWindow()
{
InitializeComponent();
root = new TreeViewItem
{
Header = "Customers"
};
treeView.Items.Add(root);
addNode("John");
addNode("Peter");
addNode("Vanesa.New");
addNode("Josh");
addNode("Josh.New");
addNode("Josh.New.Under");
}
private void addNode(string values)
{
var n = root;
foreach (var val in values.Split('.'))
{
var isNew = true;
foreach (var existingNode in n.Items)
{
if (((TreeViewItem)existingNode).Header.ToString() == val)
{
n = (TreeViewItem)existingNode;
isNew = false;
}
}
if (isNew)
{
var newNode = new TreeViewItem
{
Header = val
};
n.Items.Add(newNode);
n = newNode;
}
}
}
I had the same problem. i solved that in this way:
defining a class that implement a tree:
class TreeBuilder
{
public int index,depth;
public string text;
public Dictionary<string,TreeBuilder> childs;
public void addToTreeVeiw(System.Windows.Forms.TreeNode root, TreeBuilder tb) {
foreach (string key in tb.childs.Keys) {
System.Windows.Forms.TreeNode t = root.Nodes.Add(tb.childs[key].text);
addToTreeVeiw(t, tb.childs[key]);
}
}
}
and the main part:
string[] lis = {"a","b","a.a","a.ab","c","cc.a","a.b.dd","samad.hah.hoh"};
treeView1.Nodes.Clear();
TreeBuilder Troot = new TreeBuilder();
TreeBuilder son;
Troot.depth = 0;
Troot.index = 0;
Troot.text = "root";
Troot.childs = new Dictionary<string, TreeBuilder>();
foreach (string str in lis)
{
string[] seperated = str.Split('.');
son = Troot;
int index= 0;
for (int depth = 0; depth < seperated.Length; depth++)
{
if (son.childs.ContainsKey(seperated[depth]))
{
son = son.childs[seperated[depth]];
}
else {
son.childs.Add(seperated[depth],new TreeBuilder());
son = son.childs[seperated[depth]];
son.index= ++index;
son.depth = depth+1;
son.text = seperated[depth];
son.childs = new Dictionary<string, TreeBuilder>();
}
}
}
treeView1.Nodes.Add("root");
Troot.addToTreeVeiw(treeView1.Nodes[0], Troot);
I guess result is what you want:
Re #charles380 solution:
I have updated the code to work with WPF .Net Core tree view.
public class TreeNodeHierarchy
{
public int Level { get; set; }
public TreeViewItem Node { get; set; }
public Guid Id { get; set; }
public Guid ParentId { get; set; }
public string RootText { get; set; }
}
public class TreeManager{
public List<TreeNodeHierarchy> overAllNodeList;
public void AddNodes(IEnumerable<string> data, ref TreeView treeView1)
{
overAllNodeList = new List<TreeNodeHierarchy>();
foreach (var item in data)
{
//\test
var nodeList = new List<TreeNodeHierarchy>();
var split = item.Split('.', StringSplitOptions.RemoveEmptyEntries);
for (var i = 0; i < split.Count(); i++)
{
var guid = Guid.NewGuid();
var parent = i == 0 ? null : nodeList.First(n => n.Level == i - 1);
var root = i == 0 ? null : nodeList.First(n => n.Level == 0);
nodeList.Add(new TreeNodeHierarchy
{
Level = i,
Node = new TreeViewItem { Header = split[i], Tag = guid },
Id = guid,
ParentId = parent != null ? parent.Id : Guid.Empty,
RootText = root != null ? root.RootText : split[i]
});
}
// figure out dups here
if (!overAllNodeList.Any())
{
overAllNodeList.AddRange(nodeList);
}
else
{
nodeList = nodeList.OrderBy(x => x.Level).ToList();
for (var i = 0; i < nodeList.Count; i++)
{
var existingNode = overAllNodeList.FirstOrDefault(
n => n.Node.Header.ToString() == nodeList[i].Node.Header.ToString() && n.Level == nodeList[i].Level && n.RootText == nodeList[i].RootText);
if (existingNode != null && (i + 1) < nodeList.Count)
{
nodeList[i + 1].ParentId = existingNode.Id;
}
else
{
overAllNodeList.Add(nodeList[i]);
}
}
}
}
foreach (var treeNodeHierachy in overAllNodeList.Where(x => x.Level == 0))
{
treeView1.Items.Add(AddChildNodes(treeNodeHierachy));
}
}
private TreeViewItem AddChildNodes(TreeNodeHierarchy node)
{
var treeNode = node.Node;
foreach (var treeNodeHierachy in overAllNodeList.Where(n => n.ParentId == node.Id))
{
treeNode.Items.Add(AddChildNodes(treeNodeHierachy));
}
return treeNode;
}
}
}
Sample calling code:
var lstFolders= new List<string>
{
"John",
"Peter",
"Vanesa",
"Vanesa.New",
"Josh",
"Josh.New",
"Josh.New.Under",
"Josh.Old"
};
TreeManager treeManager = new TreeManager();
treeManager.AddNodes(lstFolders, ref tr);
The following code is designed so that if I change the array assigned to one node it will not affect the other node.
My question is: Is there a more "idiomatic" way to accomplish this?
void Main()
{
var arr = new [] { 1, 2, 3 };
var node1 = new Node();
node1.Children = arr;
var node2 = new Node();
node2.Children = arr;
node1.Children[0] = 9; // node2 SHOULD NOT be affected by this
node1.Dump();
node2.Dump();
}
class Node
{
private int[] children;
public int[] Children
{
get { return children; }
set
{
children = new int[value.Length];
value.CopyTo(children, 0);
}
}
}
What about this [EDITED]:
class Node
{
private int[] _children;
public Node(int[] children)
{
this._children = (int[])children.Clone();//HERE IS THE IDEA YOU ARE LOOKING FOR
}
public int this[int index]
{
get { return this._children[index]; }
set { this._children[index] = value; }
}
}
I think you would be better off changing the array object copy semantics rather than adding features to the Node class to support this. Fortunately there is already a class with the semantics you are looking for: List.
This simplifies the Node class:
class Node
{
public List<int> Children { get; set; }
}
The result:
static void Main(string[] args)
{
var arr = new[] { 1, 2, 3 };
var node1 = new Node
{
Children = new List<int>(arr)
};
var node2 = new Node
{
Children = new List<int>(node1.Children)
};
node1.Children[0] = 9; // node2 SHOULD NOT be affected by this
Console.WriteLine("First element node1:{0}, first element node2:{1}",
node1.Children[0], node2.Children[0]);
}
still new to the world of linq, and i need some help flatening a list of parents that have children, into a single list of ParentChild's.
Just like this:
class Program
{
static void Main()
{
List<Parent> parents = new List<Parent>();
parents.Add(new Parent { Name = "Parent1", Children = new List<Child> { new Child { Name = "Child1" }, new Child { Name = "Child2" } } });
parents.Add(new Parent { Name = "Parent2", Children = new List<Child> { new Child { Name = "Child3" }, new Child { Name = "Child4" } } });
// linq query to return List<ParentChild> parentChildList;
// ParentName = Parent1, ChildName = Child1
// ParentName = Parent1, ChildName = Child2
// ParentName = Parent2, ChildName = Child3
// ParentName = Parent2, ChildName = Child4
}
internal class ParentChild
{
public string ParentName { get; set; }
public string ChildName { get; set; }
}
internal class Parent
{
public string Name { get; set; }
public List<Child> Children { get; set; }
}
internal class Child
{
public string Name { get; set; }
}
}
Many thanks,
Chris
from parent in parents
from child in parent.Children
select new ParentChild() { ParentName = parent.Name, ChildName = child.Name };
This should do it for you:
var k = from p in parents
from c in p.Children
select new {Name = p.Name, Child = c.Name };
EDIT: Opps forgot to return a new ParentChild object. but Kent beat me to it ;)