none
Incrementing a list key within a for loop RRS feed

  • Question

  • Hi,

      I'm trying to set an increment on a property of a list within my for loop parameters, such that the first instance generated by the loop takes the first list value and subsequent instances take key values incrementing by 1. I'm first reducing the list to a list of only the required value type, then trying to increment the key in the for loop parameters, then passing it into a method within the for loop. I'm not sure if I've simply got the syntax slightly wrong or if I'm a bit further from the mark than I had thought. My code looks like this:

    List<int> Dist1 = new List<int>();
                foreach (var Measure in TempOpenings)
                {
                    Dist1.Add(InputHHeight);
                }
    
                int DoorCount = 1;
                int WindowCount = 1;
                int BHO = 8;
                for (int i = 0; i < Accounts.Count; i++, BHO += 75, DoorCount += 1, WindowCount += 1, Dist1.ElementAt(i += 1))
                {
                    string OpeningSpecs()
                    {
                        if (InputCHeight == 0)
                        {
                            string Specs = $"W: {InputOWidth} HH: {Dist1.ElementAt(0)}";
                            return Specs;
                        }
                        else
                        {
                            string CillRequired = "CH: ";
                            string Specs = $"W: {InputOWidth} HH: {Dist1.ElementAt(0)} {CillRequired}{InputCHeight}";
                            return Specs;
                        }
                    }
                }

    Any help would be appreciated, 

    Thanks,

    Matthew




    • Edited by matty1248 Saturday, March 9, 2019 11:06 PM
    Saturday, March 9, 2019 5:32 PM

Answers

  • Matthew, you said:

    >>There's also a slightly simplified version of the same problem in 'ConcPhysControlModule' (which i probably should have used in the first place), in this case the 'DistFromSOP' reference needs to be calling incrementing key values from the same list:<<

    OK, so then why do you pass both TempOpenings and DistFromSOP in the constructor for ConcPhysControlModule? Seems to be that you just need to use TempOpenings for that. So, in your TrueOfActual() method, could you this instead:

    for (int i = 0; i < Accounts.Count; i++, BHO += 75)
    {
        TextBlock FromSOPLength = new TextBlock()
        // I think that I used the correct property of the OpeningMembers class, which the TempOpenings list contains
        // If not, you would know more than I which property it should be
        { Text = $"From SOP: {TempOpenings[i].OpeningFromSOP}", Margin = new Thickness(4, BHO, 4, 0), Style = Style1 };
    


    ~~Bonnie DeWitt [C# MVP]

    http://geek-goddess-bonnie.blogspot.com

    • Marked as answer by matty1248 Sunday, March 10, 2019 10:58 PM
    Sunday, March 10, 2019 10:50 PM
    Moderator

All replies


  •   I'm trying to set an increment on a property of a list within my for loop parameters, such that the first instance generated by the loop takes the first list value and subsequent instances take key values incrementing by 1. I'm first reducing the list to a list of only the required value type, then trying to increment the key in the for loop parameters, then passing it into a method within the for loop. I'm not sure if I've simply got the syntax slightly wrong or if I'm a bit further from the mark than I had thought. 

    List<int> Dist1 = new List<int>();
                foreach (var Measure in TempOpenings)
                {
                    Dist1.Add(InputHHeight);
                }
    
                int DoorCount = 1;
                int WindowCount = 1;
                int BHO = 8;
                for (int i = 0; i < Accounts.Count; i++, BHO += 75, DoorCount += 1, WindowCount += 1, Dist1.ElementAt(i += 1))
                {
                    string OpeningSpecs()
                    {
                        if (InputCHeight == 0)
                        {
                            string Specs = $"W: {InputOWidth} HH: {Dist1.ElementAt(0)}";
                            return Specs;
                        }
                        else
                        {
                            string CillRequired = "CH: ";
                            string Specs = $"W: {InputOWidth} HH: {Dist1.ElementAt(0)} {CillRequired}{InputCHeight}";
                            return Specs;
                        }
                    }
                }


    You haven't given us any clue as to what you see happening that's wrong.
    You haven't told us what you are expecting and what you are getting.

    A couple of questions came to mind on a first look at your code:

    (1) In the for loop what do you think this expression does?

    Dist1.ElementAt(i += 1)

    (2) In your conditional you are always using Dist1.ElementAt(0).
        Is that what you meant to do?
        
    - Wayne
        

    Saturday, March 9, 2019 10:55 PM
  • Hi Wayne, thanks for your response.

    I was hoping the 'Dist1.ElementAt(i += 1)' expression would iterate through the keys in the list and return the values for those keys, starting at the 0th value to a maximum of the for loop range. 

    With regards to the 'Dist1.ElementAt(0)' condition, I wasn't sure if it should be a 1 or a 0 within the brackets, i guess i just wated it to start at the first item in the list so that the += operator would act on subsequent list entries. 

    I'm terrible at explaining these things, hope this helps.

    Thanks again,

    Matthew

    Saturday, March 9, 2019 11:14 PM

  • I was hoping the 'Dist1.ElementAt(i += 1)' expression would iterate through the keys in the list and return the values for those keys, starting at the 0th value to a maximum of the for loop range. 


    You really should be using the debugger and stepping through your code to
    watch what happens to every variable during execution. Let's break down the
    for loop steps:

    for (int i = 0; i < Accounts.Count; i++, BHO += 75, DoorCount += 1, WindowCount += 1, Dist1.ElementAt(i += 1))

    On the first iteration of the loop i will be at 0.

    On the next iteration what happens (in order) is:

    If i is < Accounts.Count then the third part of the for statement gets processed.

    i is incremented by 1 so at the start of the second iteration i == 1

    Then BHO is incremented by 75

    Then DoorCount is incremented by 1

    Then WindowCount is incremented by 1

    Then the expression (i += 1) is evaluated and as a result i is incremented by 
    1 again and is now == 2.

    The method Dist1.ElementAt(i) is invoked and returns the value of the element
    at that index (2), but you do nothing with that value.

    Is that really what you wanted to do?

    - Wayne


    • Edited by WayneAKing Sunday, March 10, 2019 12:51 AM
    Saturday, March 9, 2019 11:44 PM
  • No, it's totally disfunctional :/ , that's why I'm stuck. The 'BHO' value is incrementing the distance of the UIElement group correctly, the 'DoorCount' and 'WindowCount' are correctly incrementing the name of the opening, but I need to find a method which i can apply similarly for all the other values which calls on values from incrementing keys in an independant list. The code as per the original post doesn't even run, I just added it to show indicatively what I'm trying to do, flawed though it is. I can't seem to find a way,

    Cheers,

    Matthew


    • Edited by matty1248 Sunday, March 10, 2019 12:19 AM
    Sunday, March 10, 2019 12:17 AM
  •  The code as per the original post doesn't even run, I just added it to show indicatively what I'm trying to do, flawed though it is. 


    Well, it's very hard to visualize what you are trying to do based on your
    narratives alone. If you could give concrete examples of the contents of
    the list(s), plus examples of how they are to be processed and the end
    result(s) then we might be better able to get inside your mind. Unfortunately
    your code examples may just be obscuring the objective rather than clarifying
    it. For example, inside your for() loop you have *defined* a local function
    (which in itself is uncommon practice) but nowhere do you call that function
    so it never gets executed.

    - Wayne

    Sunday, March 10, 2019 1:07 AM
  • Good morning, 

       well the list itself is declared within an abstract class then instantiated in a click event which runs every time the 'Add to template "ADD"' button is clicked (as in the image above), submitting all the inputs above it to the list item. 

       I was really unsure as to whether the functions should go within the for loop in this case, I don't normally do that, they are called a little further down in the loop as below (i had removed the calling instances to try to simplify), this is the bulk of the loop:

    for (int i = 0; i < Accounts.Count; i++, BHO += 75, DoorCount += 1, WindowCount += 1)
                {
                    string OpeningSpecs()
                    {
                        if (InputCHeight == 0)
                        {
                            string Specs = $"W: {InputOWidth} HH: {InputHHeight}";
                            return Specs;
                        }
                        else
                        {
                            string CillRequired = "CH: ";
                            string Specs = $"W: {InputOWidth} HH: {InputHHeight} {CillRequired}{InputCHeight}";
                            return Specs;
                        }
                    }
                    string OpeningCode()
                    {
                        if (InputCHeight == 0)
                        {
                            if (LintelCheck == true)
                            {
                                string Specs = $"D{TemplateCodeAmmendment()}{DoorCount}: With lintel";
                                return Specs;
                            }
                            else
                            {
                                string Specs = $"D{TemplateCodeAmmendment()}{DoorCount}: No lintel";
                                return Specs;
                            }
                        }
                        else
                        {
                            if (LintelCheck == true)
                            {
                                string Specs = $"W{TemplateCodeAmmendment()}{WindowCount}: With lintel";
                                return Specs;
                            }
                            else
                            {
                                string Specs = $"W{TemplateCodeAmmendment()}{WindowCount}: No lintel";
                                return Specs;
                            }
                        }
                    }
    
                    TextBlock openingCode = new TextBlock()
                    { Margin = new Thickness(4, BHO, 0, 0), Text = OpeningCode(), Style = style1 };
                    OpeningInputRefModule.Add(openingCode);
                    RespPanel.Children.Add(openingCode);
    
                    Button deleteOpening = new Button()
                    { Margin = new Thickness(0, 11, 4, 0), Style = style2, Content = "DEL" };
                    deleteOpening.Click += deleteOpening_Click;
                    OpeningInputRefModule.Add(deleteOpening);
                    RespPanel.Children.Add(deleteOpening);
    
                    TextBlock openingDescription = new TextBlock()
                    { Margin = new Thickness(4, 8, 0, 0), Text = OpeningSpecs(), Style = style1 };
                    OpeningInputRefModule.Add(openingDescription);
                    RespPanel.Children.Add(openingDescription);
                }

    You can also see the full app here if it helps:

    https://drive.google.com/file/d/15NiCkaulLq5t33C-QgEpY7mqxdsDiL4s/view?usp=sharing

    It's all in aid of making the 'DEL' button work for each created template opening instance, the button works fine now, but lots of functionality that worked fine before has been lost. All the remaining logics depend on this same solution.

    I hope this helps, 

    thanks for taking a look,

    Matthew



    • Edited by matty1248 Sunday, March 10, 2019 9:12 AM
    Sunday, March 10, 2019 9:10 AM
  • Hi Matthew,

    Is there any specific reason that you have OpeningSpecs() and OpeningCode() inside the for loop? As Wayne said, this is an uncommon practice (and, you yourself said that you don't normally do that). I think you don't want to do that, it just makes your for loop look way too complicated!!   ;0)

    I downloaded your solution, but I can't even load it because I don't have UWP installed (and I didn't want to do it just for this). I have however searched through your code for Dist1 (with a search utility), and all your references to it are commented out.

    Your initial question had something to do with getting items from that Dist1 list, but now I don't know it that's still your problem/question.

    Can you elaborate, based on what I've downloaded from your GoogleDrive?


    ~~Bonnie DeWitt [C# MVP]

    http://geek-goddess-bonnie.blogspot.com

    Sunday, March 10, 2019 8:58 PM
    Moderator
  • Hello Bonnie, 

       thanks for taking a look. I think i've really confused things with this disfunctional code i've added, I just went into a previous program i'd been making and copy pasted this 'Dist1' list while i was there. I'm really unsure as to whether the OpeningSpecs() and OpeningCode() should be within the loop, the problem is that all the values within them are subject to similar incrementation. Taking the instance of the else statement in OpeningSpecs():

    else
                        {
                            string Specs = $"W: {InputOWidth} HH: {InputHHeight} CH: {InputCHeight}";
                            return Specs;
                        }

    All the referenced values here need to be calling on values from the 'TempOpenings' list, I also need to re arrange the code structure such that the 'W' is dynamic but I should be alright with that. There's also a slightly simplified version of the same problem in 'ConcPhysControlModule' (which i probably should have used in the first place), in this case the 'DistFromSOP' reference needs to be calling incrementing key values from the same list:

    public override void TrueOfActual()
            {
                int BHO = 8;
                for (int i = 0; i < Accounts.Count; i++, BHO += 75)
                {
                    TextBlock FromSOPLength = new TextBlock()
                    { Text = $"From SOP: {DistFromSOP}", Margin = new Thickness(4, BHO, 4, 0), Style = Style1 };
                    OpeningInputRefModule.Add(FromSOPLength);
                    RespPanel.Children.Add(FromSOPLength);
    
                    RelativePanel.SetAlignRightWithPanel(FromSOPLength, true);
                    RelativePanel.SetAlignTopWithPanel(FromSOPLength, true);
                }
            }

    I hope this helps, let me know if there's anything else of use to know, once I've solved this one I think I'm almost finished my program.

    Kind regards,

    Matthew

    Sunday, March 10, 2019 9:48 PM
  • Matthew, you said:

    >>There's also a slightly simplified version of the same problem in 'ConcPhysControlModule' (which i probably should have used in the first place), in this case the 'DistFromSOP' reference needs to be calling incrementing key values from the same list:<<

    OK, so then why do you pass both TempOpenings and DistFromSOP in the constructor for ConcPhysControlModule? Seems to be that you just need to use TempOpenings for that. So, in your TrueOfActual() method, could you this instead:

    for (int i = 0; i < Accounts.Count; i++, BHO += 75)
    {
        TextBlock FromSOPLength = new TextBlock()
        // I think that I used the correct property of the OpeningMembers class, which the TempOpenings list contains
        // If not, you would know more than I which property it should be
        { Text = $"From SOP: {TempOpenings[i].OpeningFromSOP}", Margin = new Thickness(4, BHO, 4, 0), Style = Style1 };
    


    ~~Bonnie DeWitt [C# MVP]

    http://geek-goddess-bonnie.blogspot.com

    • Marked as answer by matty1248 Sunday, March 10, 2019 10:58 PM
    Sunday, March 10, 2019 10:50 PM
    Moderator
  • Bonnie, that's so great! I can't thank you enough, I've been attacking this same problem of trying to get the delete button to work for literally months. I really appreciate that,  :) :) :)
    Sunday, March 10, 2019 10:58 PM
  • Oh!! Does that mean it worked?!?! 

    ~~Bonnie DeWitt [C# MVP]

    http://geek-goddess-bonnie.blogspot.com

    Sunday, March 10, 2019 10:59 PM
    Moderator
  • Yeah, it worked great, though there seems to be something else going on in the larger method because I can't apply that code analogously. Hopefully I'll suss it out fairly quickly, I'm sure this is the solution,

    many thanks,

    Matthew

    Sunday, March 10, 2019 11:05 PM
  • Glad I could help, Matthew!  But, I gotta tell you, it was tough following what you were doing because I couldn't actually Load the project (my problem, as I said earlier, not having UWP installed), so I just had individual files open and tried to follow what came from where and went to there … whew!!!   ;0)


    ~~Bonnie DeWitt [C# MVP]

    http://geek-goddess-bonnie.blogspot.com

    Sunday, March 10, 2019 11:05 PM
    Moderator
  • Hopefully I'll suss it out fairly quickly,

    Hopefully! Post again if you can't!  =0)

    ~~Bonnie DeWitt [C# MVP]

    http://geek-goddess-bonnie.blogspot.com

    Sunday, March 10, 2019 11:07 PM
    Moderator
  • I got it now, just some small details to iron out which i think i'll have to add additional lists for and then some minor that i solved in previous attempts to build this program.

    I'm going to present it at my work later this week and hopefully they will let me do some coding :D.

    PS. I know my code must be a nightmare and I'm sure you saw some terrible things :D, nice job picking through it blind

    Best regards,

    Matthew


    • Edited by matty1248 Sunday, March 10, 2019 11:25 PM
    Sunday, March 10, 2019 11:21 PM
  • Nah, not a nightmare at all … it's just a complicated business domain!!  Are you an architect (or work for an architecture firm)?

    ~~Bonnie DeWitt [C# MVP]

    http://geek-goddess-bonnie.blogspot.com

    Sunday, March 10, 2019 11:33 PM
    Moderator
  • Yeh, it's very complicated, and I'm really pleased with it, but i think business is maybe not very well defined from the presentation and I am working with a limited set of rules at the moment which probably lengthens my code. I'm an ex building designer/project manager, now i work for a company that makes engineering/architectural software to sell it's building products with, I'm hoping to hone my coding skills with them so I can build some good products. 
    Sunday, March 10, 2019 11:42 PM
  • Cool!  Good luck!  =0)

    ~~Bonnie DeWitt [C# MVP]

    http://geek-goddess-bonnie.blogspot.com

    Sunday, March 10, 2019 11:49 PM
    Moderator
  • Thanks Bonnie, and thanks again for your help :)
    Sunday, March 10, 2019 11:52 PM

  •   I'm trying to set an increment on a property of a list within my for loop parameters, such that the first instance generated by the loop takes the first list value and subsequent instances take key values incrementing by 1. I'm first reducing the list to a list of only the required value type, then trying to increment the key in the for loop parameters, then passing it into a method within the for loop. 


    A word about terminology. Your use of the term "key" in reference to a List
    adds somewhat to the confusion some of us have experienced with your posts.
    Most often when "key" is used in relation to a container it is used with
    reference to a Dictionary. Each item in an object of that class type has
    two parts - a Key and a Value. Items in the Dictionary can be referenced via
    their Keys.

    A List on the other hand has no part, property, etc. that is referred to as
    a "key". A careful reading of the documentation for the List class will
    likely fail to turn up any such terminology. (Note that some of the extension
    methods that can be used with List do have TKey parameters, such as GroupBy.)
    So your use of "key" when talking about a list probably strikes most programmers
    here as unusual and vague.

    List<T> Class
    https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.list-1?view=netframework-4.7.2

    Most often when wishing to iterate over the items in a List one uses an indexer: [ ]

    List<T>.Item[Int32] Property
    https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.list-1.item?view=netframework-4.7.2#System_Collections_Generic_List_1_Item_System_Int32_

    "Gets or sets the element at the specified index."

    Using indexers (C# Programming Guide)
    https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/indexers/using-indexers

    Your reference to incrementing "key values" can be misinterpreted as meaning
    that values in the list itself are to be incremented rather than an index 
    into the list. Use of conventional terms can go a long way toward making clear
    what you want to do. Especially in the absence of any clear examples of the 
    desired action and result.

    - Wayne

    Monday, March 11, 2019 6:16 PM
  • Hi Wayne, 

       I see, I hadn't appreciated that key was a term only associated with dictionary's, I'm so used to attacking problems on my own and just using trial and error that often I get a bit lost with the terminology. Together with the fact that I'm terrible of giving a clear diagnosis of the problem it seems to lot of my initial posts hard to understand/digest. I've had a look through those documents, I'll try to look in closer detail again when I get to the end of this project, so I can refine my understanding in advance of starting out on the next project. Thanks for your help,

    regards,

    Matthew

    Tuesday, March 12, 2019 6:54 PM