Zeus Zeus - 3 months ago 19
C# Question

store parent, child, grand- child data in memory

I'm looking for the simplest method to store parent child data in memory for manipulation. There will be approx 100 parents, 20 children and 30 grand-children and only the number of parents will change, all child and grand-child properties will be known before compiling. I would like to access the grand children data using the parent ID and property name as a key. I could use a simple class with 200 odd properties, but I'm sure there's a more efficient method.

I've come across nested dictionaries/classes/structures/tuples, lists of lists, lists of arrays, json, non-binary trees etc but most posts are several years old and I'm not sure which method is best.

Please can anyone suggest which method to use or if there's a good library available?

ID (1 to 100)
|
param 1 param 2 param 3 param 4.....param 20
-val 1 -val 1 -val 1 -val 1 -val 1
-val 2 -val 2 -val 2 -val 2 -val 2
-val 3 -val 3 -val 3 -val 3 -val 3
...
-val 30 -val 30 -val 30 -val 30 -val 30

Answer

I'd start with a simple, standard approach: define a class for a tree structure and use a list collection for the children nodes and a convenient contructor to assign a parent.

 public class Node
 {
     public List<Node> children = new List<Node>();

     public string Name;
     public int? Val;

     public Node Parent = null;

     public Node(string name, int? val, Node fromParent = null) {
         Name = name;
         Val = val;
         if (fromParent != null)
         {
             Parent = fromParent;
             fromParent.children.Add(this);
         }
     }

 }

A trivial usage:

var parent1 = new Node("parent1",10);
var child1 = new Node("child", 30, parent1);

Inheritance example

Subclasses

public class Root : Node
{
    public int ParentID;
    public Root(int id) : base(null, null, null)
    {
        ParentID = id;
    }
}

public class Parameter : Node
{
    public string ParameterType;
    public Parameter(string paramName, string paramType, Node fromParent = null) : base(paramName, null, fromParent)
    {
        ParameterType = paramType;
    }
}
public class Value : Node
{
    public string Unit;
    public Value(int val, string unit, Node fromParent = null) : base(null, val, fromParent)
    {
        Unit = unit;
    }
}

and how to instantiate them (with random values)

List<Node> parents = new List<Node>();
Random rnd = new Random();
for (int k = 0; k < 100; k++)
{
    var parentk = new Root(k);
    for (int kk = 0; kk < 20; kk++)
    {
        var paramkk = new Parameter("simple" + kk, "param1", parentk);
        for (int kkk = 0; kkk < 30; kkk++)
        {
            int dice = rnd.Next(1, 1000000);
            var valkkk = new Value(dice, "bar", paramkk);
        }

    }
    parents.Add(parentk);
}

in-memory searches

Let's say you have the above collection of parents and you want to find the one with max value for param1

DateTime start = DateTime.Now;
var mySearch = parents.SelectMany(x => x.children)
    .Where(x => ((Parameter)x).ParameterType == "param1")
  .GroupBy(x => x.Parent,
    x => x.children,
    (key, gr) =>
    new
    {
        Key = key,
        MaxVal = gr.Max(y => y.Max(z => z.Val))
    }).OrderByDescending(x => x.MaxVal).First();
var foundID = ((Root)mySearch.Key).ParentID;
DateTime stop  = DateTime.Now;

var elapsed = (stop - start).TotalMilliseconds;

and this search took about 15 milliseconds on my laptop

Comments