0

I have three lists of objects each of which are linked to one other list by a single common property, Parent and Node in the following hierarchy: Model -> Intermediate -> Results. I have the following code:

class Result
{
    public string Name { get; set; }
    public int Node{ get; set; }
    public int Parent{ get; set; }
}
class Intermediate
{
    public int Node{ get; set; }
    public int Parent{ get; set; }
}
class Model
{
    public string Name { get; set; }
    public int Node{ get; set; }
    public int Parent{ get; set; }
}

public class Example
{
    public static void Main()
    {
        List<Result> results = new List<Result>();
        List<Intermediate> intermediates = new List<Intermediate>();
        List<Model> models = new List<Model>();

        // Example objects in the list
        results.Add(new Result() { Name = "", Parent = 21, Node = 101 });
        intermediates.Add(new Part() { Parent = 11, Node = 21 });
        models.Add(new Part() { Name = "ABCD", Parent = 1, Node = 11 });
        ...
    }
}

As can be seen the Model object links to Intermediate object via model.Node and intermediate.Parent, and the Intermediate object links to Results object via intermediate.Node and results.Parent. Note the lists can contain thousands of items, each added using a similar format as above.

What I want to be able to do is add the names from the Model objects in list to the matching Results objects in the results list.

My thinking is that I can loop through each object in the Intermediate list and find (using LINQ) the Result object where intermediate.Node = result.Parent, and then either replace the value of the result.Parent with intermediate.Parent, or add a new Grandparent property to the Result object in which to put the intermediate.Parent. Then repeat the process looping through each of the objects in the models list finding the matching Result object and adding the Name.

So I guess my question is, is this the best way of doing this, or is there a more efficient way? I have many lists where the same will have to be repeated, so was wondering if there was a better way as it can be quite slow looping through every object. Also is there a way to get from the first list directly to the third list.

I hope this is well enough explained. I am quite a beginner when it comes to C#.

3
  • You'd need to make a common interface in order to put them in the same list. Also, why not have a direct reference to the object instead of an int. Commented Oct 21, 2015 at 13:42
  • It seems like bad model(I mean data-model, not your class definition) design. To zip lists like you have described you will have to iterate each of them anyway. Commented Oct 21, 2015 at 13:44
  • I agree that it is a bad model. The trouble is I am reading from a file that I haven't created and it seems to be the only way to "logically" read it in. I am not that experienced in C#, so the implementation may not be the best or most efficient. The above code was also only created to get my question across, so isn't exactly as implemented. Commented Oct 21, 2015 at 13:50

3 Answers 3

3

You actually have Results -> Intermediate -> Model instead of Model -> Intermediate -> Results.

To speed the process of removing the Intermediate, build a dictionary. Then you can do a simple select on Results using the dictionary to convert.

var intermediateDict=intermediates.ToDictionary(key=>key.Node,val=>val.Parent);
var newresults=results.Select(r=>new Result {
  Name=r.Name,
  Node=r.Node,
  Parent=intermediateDict[r.Parent]
  });

You can also do joins to get the final answer.

Sign up to request clarification or add additional context in comments.

Comments

1

It looks a foreach loop can be used to get to the result (leaf) nodes and assign the model name to result nodes:

var theModel = models.First(); // select a model

foreach (var interm in intermediates.Where(x => x.Parent == theModel.Node))
{
    foreach (var res in results.Where(x => x.Parent == interm.Node))
    {
        res.Name = theModel.Name;
    }
}

Comments

0

Smells like Composite Pattern what you talk about here.

And you can use HashSet to keep your values to perform it fast.

public class Item
{
    public Item(int itemNode)
    {
        Node = itemNode;
        Children = new HashSet<Item>();
    }

    public int Node { get; set; }
    public Item Parent { get; set; }
    private HashSet<Item> Children { get; set; }

    public bool Add(Item item)
    {
        item.Parent = this;
        return Children.Add(item);
    }

    public List<Item> Find(Func<Item, bool> predicate)
    {
        var found = new List<Item>();
        if (predicate(this)) found.Add(this);
        Collect(predicate, found);
        return found;
    }

    public void Collect(Func<Item, bool> predicate, List<Item> collected = null)
    {
        collected = collected ?? new List<Item>();
        collected.AddRange(Children.Where(predicate).ToList());

        foreach (var child in Children)
        {
            child.Collect(predicate, collected);
        }
    }
}

public class Model : Item //this is your model
{
    public string Name { get; set; }
    public Model(int itemNode, string name) : base(itemNode)
    {
        Name = name;
    }

    public List<Item> GetNamesMatchingWith(Func<Item, bool> predicate)
    {
        return Find(predicate);
    }
}

public class Example
{
    public static void Main()
    {
        var root = new Model(0, "root");
        var one = new Model(1, "1");
        var two = new Model(2, "2");
        var tree = new Model(3, "3");

        root.Add(one);
        root.Add(two);
        root.Add(tree);

        var a = new Model(4, "a");
        var b = new Model(5, "b");

        two.Add(a);
        two.Add(b);

        var namesMatchingWith = root.GetNamesMatchingWith(x=> x.Parent!=null && x.Parent.Node == 2);
        Console.ReadKey();
    }
}

Hope it inpires you..

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.