C# recursively calculate value












0















I have following table



enter image description here



I need to work out the values in columns X, Y and Z.



Rule 1: code only has children as X, Y, or Z.



Let's start from a simple one, row 12, code 'E2' has a child called 'Z' and value is 3.30, so cell [F12] (column Z) should have 3.30. We can denote as f(12)= 3.30Z, Similarly, cell [E11] should be 2.10, or f(11)=2.10Y. For row 6, cell[D6] should be 1.14, denote as f(6)=1.14X.



note, code X,Y,Z do not have children themselves. However, other children can have grand children, recursively.



Rule 2: If a code has a child, then the value will be its own value times whatever the child code value.



e.g. row 10, it has a child 'E2', so the value will be its value 3.10 times whatever the children (E2) value, i.e. f(10)=3.10*f(12)=3.10*3.30Z=10.23Z, cell[F10] should be 10.23



Rule 3, if a code has multiple children, then the value will be sum for all the children group by type, following Rule 2



e.g. row 5 C1 has a child D, and D has three children (X, E1, E2), the 3 children values needs to add together. f(5)=1.70*(f(8)+f(9)+f(10)). Of course, some children has X values, some has Y values, some has Z values, so when adding them up, they need to be grouped by value type, and then fill in the corresponding columns Cell[D5], Cell[E5], cell[F5]



Hope that makes sense.



This is a simplified version of the original more complicated question which has thousands of rows, and some other calculations. But not a huge table, so performance or speed is not priority consideration.



It is more of an algorithm issue, but I prefer to implement in C#










share|improve this question


















  • 2





    This is a very broad question, which makes it hard for us to answer. If you've tried something, and have a specific issue, maybe we can help with that instead?

    – Richard Everett
    Nov 27 '18 at 2:14






  • 3





    Please provide a Minimal, Complete, and Verifiable example

    – Jeremy Thompson
    Nov 27 '18 at 2:22











  • It's not clear at all which part you're stuck on. Please show the code that's not working as you expect it to (SO is not a code-writing service).

    – Rufus L
    Nov 27 '18 at 2:49













  • Peeyush. the data is correct. The code represents chemical components. For example row 6 means there is 1.14 % of component X within component C1. The original chemical code are very complicated, I replaced them with pseudo code here to simply the problem.

    – ppau2004
    Nov 27 '18 at 2:50











  • Rufus, I am not sure where to start this code. this is definitely not a for each loop and has to be some sort of recursion, but I am not sure how to do. I will continue to work on it, hopefully, get a solution and post it here. In the meantime, anyone gives me some suggestions will be highly appreciated.

    – ppau2004
    Nov 27 '18 at 2:54
















0















I have following table



enter image description here



I need to work out the values in columns X, Y and Z.



Rule 1: code only has children as X, Y, or Z.



Let's start from a simple one, row 12, code 'E2' has a child called 'Z' and value is 3.30, so cell [F12] (column Z) should have 3.30. We can denote as f(12)= 3.30Z, Similarly, cell [E11] should be 2.10, or f(11)=2.10Y. For row 6, cell[D6] should be 1.14, denote as f(6)=1.14X.



note, code X,Y,Z do not have children themselves. However, other children can have grand children, recursively.



Rule 2: If a code has a child, then the value will be its own value times whatever the child code value.



e.g. row 10, it has a child 'E2', so the value will be its value 3.10 times whatever the children (E2) value, i.e. f(10)=3.10*f(12)=3.10*3.30Z=10.23Z, cell[F10] should be 10.23



Rule 3, if a code has multiple children, then the value will be sum for all the children group by type, following Rule 2



e.g. row 5 C1 has a child D, and D has three children (X, E1, E2), the 3 children values needs to add together. f(5)=1.70*(f(8)+f(9)+f(10)). Of course, some children has X values, some has Y values, some has Z values, so when adding them up, they need to be grouped by value type, and then fill in the corresponding columns Cell[D5], Cell[E5], cell[F5]



Hope that makes sense.



This is a simplified version of the original more complicated question which has thousands of rows, and some other calculations. But not a huge table, so performance or speed is not priority consideration.



It is more of an algorithm issue, but I prefer to implement in C#










share|improve this question


















  • 2





    This is a very broad question, which makes it hard for us to answer. If you've tried something, and have a specific issue, maybe we can help with that instead?

    – Richard Everett
    Nov 27 '18 at 2:14






  • 3





    Please provide a Minimal, Complete, and Verifiable example

    – Jeremy Thompson
    Nov 27 '18 at 2:22











  • It's not clear at all which part you're stuck on. Please show the code that's not working as you expect it to (SO is not a code-writing service).

    – Rufus L
    Nov 27 '18 at 2:49













  • Peeyush. the data is correct. The code represents chemical components. For example row 6 means there is 1.14 % of component X within component C1. The original chemical code are very complicated, I replaced them with pseudo code here to simply the problem.

    – ppau2004
    Nov 27 '18 at 2:50











  • Rufus, I am not sure where to start this code. this is definitely not a for each loop and has to be some sort of recursion, but I am not sure how to do. I will continue to work on it, hopefully, get a solution and post it here. In the meantime, anyone gives me some suggestions will be highly appreciated.

    – ppau2004
    Nov 27 '18 at 2:54














0












0








0








I have following table



enter image description here



I need to work out the values in columns X, Y and Z.



Rule 1: code only has children as X, Y, or Z.



Let's start from a simple one, row 12, code 'E2' has a child called 'Z' and value is 3.30, so cell [F12] (column Z) should have 3.30. We can denote as f(12)= 3.30Z, Similarly, cell [E11] should be 2.10, or f(11)=2.10Y. For row 6, cell[D6] should be 1.14, denote as f(6)=1.14X.



note, code X,Y,Z do not have children themselves. However, other children can have grand children, recursively.



Rule 2: If a code has a child, then the value will be its own value times whatever the child code value.



e.g. row 10, it has a child 'E2', so the value will be its value 3.10 times whatever the children (E2) value, i.e. f(10)=3.10*f(12)=3.10*3.30Z=10.23Z, cell[F10] should be 10.23



Rule 3, if a code has multiple children, then the value will be sum for all the children group by type, following Rule 2



e.g. row 5 C1 has a child D, and D has three children (X, E1, E2), the 3 children values needs to add together. f(5)=1.70*(f(8)+f(9)+f(10)). Of course, some children has X values, some has Y values, some has Z values, so when adding them up, they need to be grouped by value type, and then fill in the corresponding columns Cell[D5], Cell[E5], cell[F5]



Hope that makes sense.



This is a simplified version of the original more complicated question which has thousands of rows, and some other calculations. But not a huge table, so performance or speed is not priority consideration.



It is more of an algorithm issue, but I prefer to implement in C#










share|improve this question














I have following table



enter image description here



I need to work out the values in columns X, Y and Z.



Rule 1: code only has children as X, Y, or Z.



Let's start from a simple one, row 12, code 'E2' has a child called 'Z' and value is 3.30, so cell [F12] (column Z) should have 3.30. We can denote as f(12)= 3.30Z, Similarly, cell [E11] should be 2.10, or f(11)=2.10Y. For row 6, cell[D6] should be 1.14, denote as f(6)=1.14X.



note, code X,Y,Z do not have children themselves. However, other children can have grand children, recursively.



Rule 2: If a code has a child, then the value will be its own value times whatever the child code value.



e.g. row 10, it has a child 'E2', so the value will be its value 3.10 times whatever the children (E2) value, i.e. f(10)=3.10*f(12)=3.10*3.30Z=10.23Z, cell[F10] should be 10.23



Rule 3, if a code has multiple children, then the value will be sum for all the children group by type, following Rule 2



e.g. row 5 C1 has a child D, and D has three children (X, E1, E2), the 3 children values needs to add together. f(5)=1.70*(f(8)+f(9)+f(10)). Of course, some children has X values, some has Y values, some has Z values, so when adding them up, they need to be grouped by value type, and then fill in the corresponding columns Cell[D5], Cell[E5], cell[F5]



Hope that makes sense.



This is a simplified version of the original more complicated question which has thousands of rows, and some other calculations. But not a huge table, so performance or speed is not priority consideration.



It is more of an algorithm issue, but I prefer to implement in C#







c# algorithm recursion






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 27 '18 at 2:11









ppau2004ppau2004

6410




6410








  • 2





    This is a very broad question, which makes it hard for us to answer. If you've tried something, and have a specific issue, maybe we can help with that instead?

    – Richard Everett
    Nov 27 '18 at 2:14






  • 3





    Please provide a Minimal, Complete, and Verifiable example

    – Jeremy Thompson
    Nov 27 '18 at 2:22











  • It's not clear at all which part you're stuck on. Please show the code that's not working as you expect it to (SO is not a code-writing service).

    – Rufus L
    Nov 27 '18 at 2:49













  • Peeyush. the data is correct. The code represents chemical components. For example row 6 means there is 1.14 % of component X within component C1. The original chemical code are very complicated, I replaced them with pseudo code here to simply the problem.

    – ppau2004
    Nov 27 '18 at 2:50











  • Rufus, I am not sure where to start this code. this is definitely not a for each loop and has to be some sort of recursion, but I am not sure how to do. I will continue to work on it, hopefully, get a solution and post it here. In the meantime, anyone gives me some suggestions will be highly appreciated.

    – ppau2004
    Nov 27 '18 at 2:54














  • 2





    This is a very broad question, which makes it hard for us to answer. If you've tried something, and have a specific issue, maybe we can help with that instead?

    – Richard Everett
    Nov 27 '18 at 2:14






  • 3





    Please provide a Minimal, Complete, and Verifiable example

    – Jeremy Thompson
    Nov 27 '18 at 2:22











  • It's not clear at all which part you're stuck on. Please show the code that's not working as you expect it to (SO is not a code-writing service).

    – Rufus L
    Nov 27 '18 at 2:49













  • Peeyush. the data is correct. The code represents chemical components. For example row 6 means there is 1.14 % of component X within component C1. The original chemical code are very complicated, I replaced them with pseudo code here to simply the problem.

    – ppau2004
    Nov 27 '18 at 2:50











  • Rufus, I am not sure where to start this code. this is definitely not a for each loop and has to be some sort of recursion, but I am not sure how to do. I will continue to work on it, hopefully, get a solution and post it here. In the meantime, anyone gives me some suggestions will be highly appreciated.

    – ppau2004
    Nov 27 '18 at 2:54








2




2





This is a very broad question, which makes it hard for us to answer. If you've tried something, and have a specific issue, maybe we can help with that instead?

– Richard Everett
Nov 27 '18 at 2:14





This is a very broad question, which makes it hard for us to answer. If you've tried something, and have a specific issue, maybe we can help with that instead?

– Richard Everett
Nov 27 '18 at 2:14




3




3





Please provide a Minimal, Complete, and Verifiable example

– Jeremy Thompson
Nov 27 '18 at 2:22





Please provide a Minimal, Complete, and Verifiable example

– Jeremy Thompson
Nov 27 '18 at 2:22













It's not clear at all which part you're stuck on. Please show the code that's not working as you expect it to (SO is not a code-writing service).

– Rufus L
Nov 27 '18 at 2:49







It's not clear at all which part you're stuck on. Please show the code that's not working as you expect it to (SO is not a code-writing service).

– Rufus L
Nov 27 '18 at 2:49















Peeyush. the data is correct. The code represents chemical components. For example row 6 means there is 1.14 % of component X within component C1. The original chemical code are very complicated, I replaced them with pseudo code here to simply the problem.

– ppau2004
Nov 27 '18 at 2:50





Peeyush. the data is correct. The code represents chemical components. For example row 6 means there is 1.14 % of component X within component C1. The original chemical code are very complicated, I replaced them with pseudo code here to simply the problem.

– ppau2004
Nov 27 '18 at 2:50













Rufus, I am not sure where to start this code. this is definitely not a for each loop and has to be some sort of recursion, but I am not sure how to do. I will continue to work on it, hopefully, get a solution and post it here. In the meantime, anyone gives me some suggestions will be highly appreciated.

– ppau2004
Nov 27 '18 at 2:54





Rufus, I am not sure where to start this code. this is definitely not a for each loop and has to be some sort of recursion, but I am not sure how to do. I will continue to work on it, hopefully, get a solution and post it here. In the meantime, anyone gives me some suggestions will be highly appreciated.

– ppau2004
Nov 27 '18 at 2:54












2 Answers
2






active

oldest

votes


















3














What you've described is a tree structure, which you can build easily enough, and then traverse recursively. You already know the parent/child relationships; you just have to create a model to represent them in code.



Start with an Element class that looks like this:



class Element
{
string Code;
Element Parent; // null if no parent
double Value;
double CalculatedValue;
List<string> Children;
}


And create a dictionary of these, keyed by code:



Dictionary<string, Element> Elements;


Go through the list, adding creating an Element for each unique element, and adding it to the dictionary:



(Note: code examples are in pseudo-C#. I don't want to get bogged down in syntax here.)



for each row
{
Element e;

// if the element doesn't exist in the dictionary, create and add it
if (!Elements.TryGetValue(code, out e))
{
e = new Element(code, value);
Elements.Add(code, e);
}
if (child != null)
{
e.Children.Add(child);
}
}


You now have a dictionary of elements, with the child relationships. You need to create the parent relationships. Easiest way is with a scan of the dictionary:



for each e in Elements
for each child in e.Children
if (child != "X" or "Y" or "Z")
Elements[child].Parent = e;


Now what you have is a forest: one or more unrooted trees. You can scan it recursively to compute your value:



double totalValue = 0;
for each e in Elements
if (e.Parent == null)
{
totalValue += calculateElementValue(e);
}
}
// at this point, totalValue should contain the total value


If I understood your rules correctly, this method should compute an individual element's value. I assumed that an element has only one of X, Y, or Z. This is a simple depth-first traversal of an element tree.



double CalculateElementValue(Element e)
{
double eValue = 0;
double childrenValue = 0;
for each child in e.Children
{
switch (child)
{
case "X": eValue = e.Value * xValue; break;
case "Y": eValue = e.Value * yValue; break;
case "Z": eValue = e.Value * zValue; break;
else
{
childrenValue += CalculateElementValue(Elements[child]);
}
}
}
return eValue * childrenValue;
}


You could include the parent assignment in the initial loop that builds the elements, but it complicates things a little bit. But unless the table has lots of rows, you probably won't notice a difference in speed.






share|improve this answer































    1














    Here are some example data structures you can use to represent your data, and recursively calculate values.



    Note that this example uses indirect recursion. I.e. Node.Evaluate() does not call itself directly, but instead calls WeightedChild.Evaluate() which in turn calls back to Node.Evaluate().



    public class Node
    {
    public Node(params WeightedChild weightedChildren)
    {
    this.WeightedChildren = weightedChildren ?? Enumerable.Empty<WeightedChild>();
    }

    IEnumerable<WeightedChild> WeightedChildren { get; }

    public double Evaluate()
    {
    return this.WeightedChildren.Any()
    ? this.WeightedChildren.Select(child => child.Evaluate()).Sum()
    : 1;
    }
    }

    public class WeightedChild
    {
    public WeightedChild(double weight, Node child)
    {
    this.Weight = weight;
    this.Child = child;
    }

    public double Weight { get; }
    Node Child { get; }

    public double Evaluate()
    {
    return this.Child.Evaluate() * this.Weight;
    }
    }


    You can then use these classes to build your data set:



    var X = new Node();
    var Y = new Node();
    var Z = new Node();
    var E2 = new Node(new WeightedChild(3.3, Z));
    var E1 = new Node(new WeightedChild(2.1, Y));
    var D = new Node(
    new WeightedChild(0.7, X),
    new WeightedChild(1.8, E1),
    new WeightedChild(3.1, E2));
    var C2 = new Node(new WeightedChild(0.9, X));
    var C1 = new Node(
    new WeightedChild(1.14, X),
    new WeightedChild(1.7, D));
    var B = new Node(
    new WeightedChild(1.3, C1),
    new WeightedChild(1.5, C2));
    var A = new Node(new WeightedChild(1.1, C1));


    You can then evaluate each node:



    Console.WriteLine($"f(E2) = {E2.Evaluate()}");
    Console.WriteLine($"f(D) = {D.Evaluate()}");
    Console.WriteLine($"f(C1) = {C1.Evaluate()}");


    Note however, that while in your example for rule 2, you are evaulating a single "D" from row 10, the set defined in this answer captures the fact that D has multiple children and therefore will give a different answer. You could address this by redefining the Ds as D1, D2 and D3, and then add them all as children of C1 etc.






    share|improve this answer

























      Your Answer






      StackExchange.ifUsing("editor", function () {
      StackExchange.using("externalEditor", function () {
      StackExchange.using("snippets", function () {
      StackExchange.snippets.init();
      });
      });
      }, "code-snippets");

      StackExchange.ready(function() {
      var channelOptions = {
      tags: "".split(" "),
      id: "1"
      };
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function() {
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled) {
      StackExchange.using("snippets", function() {
      createEditor();
      });
      }
      else {
      createEditor();
      }
      });

      function createEditor() {
      StackExchange.prepareEditor({
      heartbeatType: 'answer',
      autoActivateHeartbeat: false,
      convertImagesToLinks: true,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: 10,
      bindNavPrevention: true,
      postfix: "",
      imageUploader: {
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      },
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      });


      }
      });














      draft saved

      draft discarded


















      StackExchange.ready(
      function () {
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53491779%2fc-sharp-recursively-calculate-value%23new-answer', 'question_page');
      }
      );

      Post as a guest















      Required, but never shown

























      2 Answers
      2






      active

      oldest

      votes








      2 Answers
      2






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      3














      What you've described is a tree structure, which you can build easily enough, and then traverse recursively. You already know the parent/child relationships; you just have to create a model to represent them in code.



      Start with an Element class that looks like this:



      class Element
      {
      string Code;
      Element Parent; // null if no parent
      double Value;
      double CalculatedValue;
      List<string> Children;
      }


      And create a dictionary of these, keyed by code:



      Dictionary<string, Element> Elements;


      Go through the list, adding creating an Element for each unique element, and adding it to the dictionary:



      (Note: code examples are in pseudo-C#. I don't want to get bogged down in syntax here.)



      for each row
      {
      Element e;

      // if the element doesn't exist in the dictionary, create and add it
      if (!Elements.TryGetValue(code, out e))
      {
      e = new Element(code, value);
      Elements.Add(code, e);
      }
      if (child != null)
      {
      e.Children.Add(child);
      }
      }


      You now have a dictionary of elements, with the child relationships. You need to create the parent relationships. Easiest way is with a scan of the dictionary:



      for each e in Elements
      for each child in e.Children
      if (child != "X" or "Y" or "Z")
      Elements[child].Parent = e;


      Now what you have is a forest: one or more unrooted trees. You can scan it recursively to compute your value:



      double totalValue = 0;
      for each e in Elements
      if (e.Parent == null)
      {
      totalValue += calculateElementValue(e);
      }
      }
      // at this point, totalValue should contain the total value


      If I understood your rules correctly, this method should compute an individual element's value. I assumed that an element has only one of X, Y, or Z. This is a simple depth-first traversal of an element tree.



      double CalculateElementValue(Element e)
      {
      double eValue = 0;
      double childrenValue = 0;
      for each child in e.Children
      {
      switch (child)
      {
      case "X": eValue = e.Value * xValue; break;
      case "Y": eValue = e.Value * yValue; break;
      case "Z": eValue = e.Value * zValue; break;
      else
      {
      childrenValue += CalculateElementValue(Elements[child]);
      }
      }
      }
      return eValue * childrenValue;
      }


      You could include the parent assignment in the initial loop that builds the elements, but it complicates things a little bit. But unless the table has lots of rows, you probably won't notice a difference in speed.






      share|improve this answer




























        3














        What you've described is a tree structure, which you can build easily enough, and then traverse recursively. You already know the parent/child relationships; you just have to create a model to represent them in code.



        Start with an Element class that looks like this:



        class Element
        {
        string Code;
        Element Parent; // null if no parent
        double Value;
        double CalculatedValue;
        List<string> Children;
        }


        And create a dictionary of these, keyed by code:



        Dictionary<string, Element> Elements;


        Go through the list, adding creating an Element for each unique element, and adding it to the dictionary:



        (Note: code examples are in pseudo-C#. I don't want to get bogged down in syntax here.)



        for each row
        {
        Element e;

        // if the element doesn't exist in the dictionary, create and add it
        if (!Elements.TryGetValue(code, out e))
        {
        e = new Element(code, value);
        Elements.Add(code, e);
        }
        if (child != null)
        {
        e.Children.Add(child);
        }
        }


        You now have a dictionary of elements, with the child relationships. You need to create the parent relationships. Easiest way is with a scan of the dictionary:



        for each e in Elements
        for each child in e.Children
        if (child != "X" or "Y" or "Z")
        Elements[child].Parent = e;


        Now what you have is a forest: one or more unrooted trees. You can scan it recursively to compute your value:



        double totalValue = 0;
        for each e in Elements
        if (e.Parent == null)
        {
        totalValue += calculateElementValue(e);
        }
        }
        // at this point, totalValue should contain the total value


        If I understood your rules correctly, this method should compute an individual element's value. I assumed that an element has only one of X, Y, or Z. This is a simple depth-first traversal of an element tree.



        double CalculateElementValue(Element e)
        {
        double eValue = 0;
        double childrenValue = 0;
        for each child in e.Children
        {
        switch (child)
        {
        case "X": eValue = e.Value * xValue; break;
        case "Y": eValue = e.Value * yValue; break;
        case "Z": eValue = e.Value * zValue; break;
        else
        {
        childrenValue += CalculateElementValue(Elements[child]);
        }
        }
        }
        return eValue * childrenValue;
        }


        You could include the parent assignment in the initial loop that builds the elements, but it complicates things a little bit. But unless the table has lots of rows, you probably won't notice a difference in speed.






        share|improve this answer


























          3












          3








          3







          What you've described is a tree structure, which you can build easily enough, and then traverse recursively. You already know the parent/child relationships; you just have to create a model to represent them in code.



          Start with an Element class that looks like this:



          class Element
          {
          string Code;
          Element Parent; // null if no parent
          double Value;
          double CalculatedValue;
          List<string> Children;
          }


          And create a dictionary of these, keyed by code:



          Dictionary<string, Element> Elements;


          Go through the list, adding creating an Element for each unique element, and adding it to the dictionary:



          (Note: code examples are in pseudo-C#. I don't want to get bogged down in syntax here.)



          for each row
          {
          Element e;

          // if the element doesn't exist in the dictionary, create and add it
          if (!Elements.TryGetValue(code, out e))
          {
          e = new Element(code, value);
          Elements.Add(code, e);
          }
          if (child != null)
          {
          e.Children.Add(child);
          }
          }


          You now have a dictionary of elements, with the child relationships. You need to create the parent relationships. Easiest way is with a scan of the dictionary:



          for each e in Elements
          for each child in e.Children
          if (child != "X" or "Y" or "Z")
          Elements[child].Parent = e;


          Now what you have is a forest: one or more unrooted trees. You can scan it recursively to compute your value:



          double totalValue = 0;
          for each e in Elements
          if (e.Parent == null)
          {
          totalValue += calculateElementValue(e);
          }
          }
          // at this point, totalValue should contain the total value


          If I understood your rules correctly, this method should compute an individual element's value. I assumed that an element has only one of X, Y, or Z. This is a simple depth-first traversal of an element tree.



          double CalculateElementValue(Element e)
          {
          double eValue = 0;
          double childrenValue = 0;
          for each child in e.Children
          {
          switch (child)
          {
          case "X": eValue = e.Value * xValue; break;
          case "Y": eValue = e.Value * yValue; break;
          case "Z": eValue = e.Value * zValue; break;
          else
          {
          childrenValue += CalculateElementValue(Elements[child]);
          }
          }
          }
          return eValue * childrenValue;
          }


          You could include the parent assignment in the initial loop that builds the elements, but it complicates things a little bit. But unless the table has lots of rows, you probably won't notice a difference in speed.






          share|improve this answer













          What you've described is a tree structure, which you can build easily enough, and then traverse recursively. You already know the parent/child relationships; you just have to create a model to represent them in code.



          Start with an Element class that looks like this:



          class Element
          {
          string Code;
          Element Parent; // null if no parent
          double Value;
          double CalculatedValue;
          List<string> Children;
          }


          And create a dictionary of these, keyed by code:



          Dictionary<string, Element> Elements;


          Go through the list, adding creating an Element for each unique element, and adding it to the dictionary:



          (Note: code examples are in pseudo-C#. I don't want to get bogged down in syntax here.)



          for each row
          {
          Element e;

          // if the element doesn't exist in the dictionary, create and add it
          if (!Elements.TryGetValue(code, out e))
          {
          e = new Element(code, value);
          Elements.Add(code, e);
          }
          if (child != null)
          {
          e.Children.Add(child);
          }
          }


          You now have a dictionary of elements, with the child relationships. You need to create the parent relationships. Easiest way is with a scan of the dictionary:



          for each e in Elements
          for each child in e.Children
          if (child != "X" or "Y" or "Z")
          Elements[child].Parent = e;


          Now what you have is a forest: one or more unrooted trees. You can scan it recursively to compute your value:



          double totalValue = 0;
          for each e in Elements
          if (e.Parent == null)
          {
          totalValue += calculateElementValue(e);
          }
          }
          // at this point, totalValue should contain the total value


          If I understood your rules correctly, this method should compute an individual element's value. I assumed that an element has only one of X, Y, or Z. This is a simple depth-first traversal of an element tree.



          double CalculateElementValue(Element e)
          {
          double eValue = 0;
          double childrenValue = 0;
          for each child in e.Children
          {
          switch (child)
          {
          case "X": eValue = e.Value * xValue; break;
          case "Y": eValue = e.Value * yValue; break;
          case "Z": eValue = e.Value * zValue; break;
          else
          {
          childrenValue += CalculateElementValue(Elements[child]);
          }
          }
          }
          return eValue * childrenValue;
          }


          You could include the parent assignment in the initial loop that builds the elements, but it complicates things a little bit. But unless the table has lots of rows, you probably won't notice a difference in speed.







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Nov 27 '18 at 6:26









          Jim MischelJim Mischel

          107k12130250




          107k12130250

























              1














              Here are some example data structures you can use to represent your data, and recursively calculate values.



              Note that this example uses indirect recursion. I.e. Node.Evaluate() does not call itself directly, but instead calls WeightedChild.Evaluate() which in turn calls back to Node.Evaluate().



              public class Node
              {
              public Node(params WeightedChild weightedChildren)
              {
              this.WeightedChildren = weightedChildren ?? Enumerable.Empty<WeightedChild>();
              }

              IEnumerable<WeightedChild> WeightedChildren { get; }

              public double Evaluate()
              {
              return this.WeightedChildren.Any()
              ? this.WeightedChildren.Select(child => child.Evaluate()).Sum()
              : 1;
              }
              }

              public class WeightedChild
              {
              public WeightedChild(double weight, Node child)
              {
              this.Weight = weight;
              this.Child = child;
              }

              public double Weight { get; }
              Node Child { get; }

              public double Evaluate()
              {
              return this.Child.Evaluate() * this.Weight;
              }
              }


              You can then use these classes to build your data set:



              var X = new Node();
              var Y = new Node();
              var Z = new Node();
              var E2 = new Node(new WeightedChild(3.3, Z));
              var E1 = new Node(new WeightedChild(2.1, Y));
              var D = new Node(
              new WeightedChild(0.7, X),
              new WeightedChild(1.8, E1),
              new WeightedChild(3.1, E2));
              var C2 = new Node(new WeightedChild(0.9, X));
              var C1 = new Node(
              new WeightedChild(1.14, X),
              new WeightedChild(1.7, D));
              var B = new Node(
              new WeightedChild(1.3, C1),
              new WeightedChild(1.5, C2));
              var A = new Node(new WeightedChild(1.1, C1));


              You can then evaluate each node:



              Console.WriteLine($"f(E2) = {E2.Evaluate()}");
              Console.WriteLine($"f(D) = {D.Evaluate()}");
              Console.WriteLine($"f(C1) = {C1.Evaluate()}");


              Note however, that while in your example for rule 2, you are evaulating a single "D" from row 10, the set defined in this answer captures the fact that D has multiple children and therefore will give a different answer. You could address this by redefining the Ds as D1, D2 and D3, and then add them all as children of C1 etc.






              share|improve this answer






























                1














                Here are some example data structures you can use to represent your data, and recursively calculate values.



                Note that this example uses indirect recursion. I.e. Node.Evaluate() does not call itself directly, but instead calls WeightedChild.Evaluate() which in turn calls back to Node.Evaluate().



                public class Node
                {
                public Node(params WeightedChild weightedChildren)
                {
                this.WeightedChildren = weightedChildren ?? Enumerable.Empty<WeightedChild>();
                }

                IEnumerable<WeightedChild> WeightedChildren { get; }

                public double Evaluate()
                {
                return this.WeightedChildren.Any()
                ? this.WeightedChildren.Select(child => child.Evaluate()).Sum()
                : 1;
                }
                }

                public class WeightedChild
                {
                public WeightedChild(double weight, Node child)
                {
                this.Weight = weight;
                this.Child = child;
                }

                public double Weight { get; }
                Node Child { get; }

                public double Evaluate()
                {
                return this.Child.Evaluate() * this.Weight;
                }
                }


                You can then use these classes to build your data set:



                var X = new Node();
                var Y = new Node();
                var Z = new Node();
                var E2 = new Node(new WeightedChild(3.3, Z));
                var E1 = new Node(new WeightedChild(2.1, Y));
                var D = new Node(
                new WeightedChild(0.7, X),
                new WeightedChild(1.8, E1),
                new WeightedChild(3.1, E2));
                var C2 = new Node(new WeightedChild(0.9, X));
                var C1 = new Node(
                new WeightedChild(1.14, X),
                new WeightedChild(1.7, D));
                var B = new Node(
                new WeightedChild(1.3, C1),
                new WeightedChild(1.5, C2));
                var A = new Node(new WeightedChild(1.1, C1));


                You can then evaluate each node:



                Console.WriteLine($"f(E2) = {E2.Evaluate()}");
                Console.WriteLine($"f(D) = {D.Evaluate()}");
                Console.WriteLine($"f(C1) = {C1.Evaluate()}");


                Note however, that while in your example for rule 2, you are evaulating a single "D" from row 10, the set defined in this answer captures the fact that D has multiple children and therefore will give a different answer. You could address this by redefining the Ds as D1, D2 and D3, and then add them all as children of C1 etc.






                share|improve this answer




























                  1












                  1








                  1







                  Here are some example data structures you can use to represent your data, and recursively calculate values.



                  Note that this example uses indirect recursion. I.e. Node.Evaluate() does not call itself directly, but instead calls WeightedChild.Evaluate() which in turn calls back to Node.Evaluate().



                  public class Node
                  {
                  public Node(params WeightedChild weightedChildren)
                  {
                  this.WeightedChildren = weightedChildren ?? Enumerable.Empty<WeightedChild>();
                  }

                  IEnumerable<WeightedChild> WeightedChildren { get; }

                  public double Evaluate()
                  {
                  return this.WeightedChildren.Any()
                  ? this.WeightedChildren.Select(child => child.Evaluate()).Sum()
                  : 1;
                  }
                  }

                  public class WeightedChild
                  {
                  public WeightedChild(double weight, Node child)
                  {
                  this.Weight = weight;
                  this.Child = child;
                  }

                  public double Weight { get; }
                  Node Child { get; }

                  public double Evaluate()
                  {
                  return this.Child.Evaluate() * this.Weight;
                  }
                  }


                  You can then use these classes to build your data set:



                  var X = new Node();
                  var Y = new Node();
                  var Z = new Node();
                  var E2 = new Node(new WeightedChild(3.3, Z));
                  var E1 = new Node(new WeightedChild(2.1, Y));
                  var D = new Node(
                  new WeightedChild(0.7, X),
                  new WeightedChild(1.8, E1),
                  new WeightedChild(3.1, E2));
                  var C2 = new Node(new WeightedChild(0.9, X));
                  var C1 = new Node(
                  new WeightedChild(1.14, X),
                  new WeightedChild(1.7, D));
                  var B = new Node(
                  new WeightedChild(1.3, C1),
                  new WeightedChild(1.5, C2));
                  var A = new Node(new WeightedChild(1.1, C1));


                  You can then evaluate each node:



                  Console.WriteLine($"f(E2) = {E2.Evaluate()}");
                  Console.WriteLine($"f(D) = {D.Evaluate()}");
                  Console.WriteLine($"f(C1) = {C1.Evaluate()}");


                  Note however, that while in your example for rule 2, you are evaulating a single "D" from row 10, the set defined in this answer captures the fact that D has multiple children and therefore will give a different answer. You could address this by redefining the Ds as D1, D2 and D3, and then add them all as children of C1 etc.






                  share|improve this answer















                  Here are some example data structures you can use to represent your data, and recursively calculate values.



                  Note that this example uses indirect recursion. I.e. Node.Evaluate() does not call itself directly, but instead calls WeightedChild.Evaluate() which in turn calls back to Node.Evaluate().



                  public class Node
                  {
                  public Node(params WeightedChild weightedChildren)
                  {
                  this.WeightedChildren = weightedChildren ?? Enumerable.Empty<WeightedChild>();
                  }

                  IEnumerable<WeightedChild> WeightedChildren { get; }

                  public double Evaluate()
                  {
                  return this.WeightedChildren.Any()
                  ? this.WeightedChildren.Select(child => child.Evaluate()).Sum()
                  : 1;
                  }
                  }

                  public class WeightedChild
                  {
                  public WeightedChild(double weight, Node child)
                  {
                  this.Weight = weight;
                  this.Child = child;
                  }

                  public double Weight { get; }
                  Node Child { get; }

                  public double Evaluate()
                  {
                  return this.Child.Evaluate() * this.Weight;
                  }
                  }


                  You can then use these classes to build your data set:



                  var X = new Node();
                  var Y = new Node();
                  var Z = new Node();
                  var E2 = new Node(new WeightedChild(3.3, Z));
                  var E1 = new Node(new WeightedChild(2.1, Y));
                  var D = new Node(
                  new WeightedChild(0.7, X),
                  new WeightedChild(1.8, E1),
                  new WeightedChild(3.1, E2));
                  var C2 = new Node(new WeightedChild(0.9, X));
                  var C1 = new Node(
                  new WeightedChild(1.14, X),
                  new WeightedChild(1.7, D));
                  var B = new Node(
                  new WeightedChild(1.3, C1),
                  new WeightedChild(1.5, C2));
                  var A = new Node(new WeightedChild(1.1, C1));


                  You can then evaluate each node:



                  Console.WriteLine($"f(E2) = {E2.Evaluate()}");
                  Console.WriteLine($"f(D) = {D.Evaluate()}");
                  Console.WriteLine($"f(C1) = {C1.Evaluate()}");


                  Note however, that while in your example for rule 2, you are evaulating a single "D" from row 10, the set defined in this answer captures the fact that D has multiple children and therefore will give a different answer. You could address this by redefining the Ds as D1, D2 and D3, and then add them all as children of C1 etc.







                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited Nov 27 '18 at 3:17

























                  answered Nov 27 '18 at 3:01









                  ErgwunErgwun

                  8,84444370




                  8,84444370






























                      draft saved

                      draft discarded




















































                      Thanks for contributing an answer to Stack Overflow!


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid



                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.


                      To learn more, see our tips on writing great answers.




                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function () {
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53491779%2fc-sharp-recursively-calculate-value%23new-answer', 'question_page');
                      }
                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown







                      Popular posts from this blog

                      Contact image not getting when fetch all contact list from iPhone by CNContact

                      count number of partitions of a set with n elements into k subsets

                      A CLEAN and SIMPLE way to add appendices to Table of Contents and bookmarks