CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 11 of 11
  1. #1
    Join Date
    Jul 2013
    Posts
    3

    Noob Needs Direction - Dynamically Named Variables in C#

    Hello Board,

    Not sure if this is titled correctly. I searched the forums with this search term and found nothing. Please excuse any ignorance with respect to language and definitoins as I am less than 1 week into C#.

    I am new to programming. I am self teaching c#. The problem arises on one of my first programs that I am doing in order to learn. I certainly don't know all the tools in the C# bag.

    I pose my question below and then provide color about the larger scope of the software program. It may be that I am asking the wrong question and there is a better solution than the direction I am going which is what I will call “dynamically declaring variable names” or “on the fly” creation of variable names. If this question means that I am not thinking about this solution to entire program properly, I would not be surprised.

    I hope I have simply stated my question below:

    How do you name (and declare) and array/list/dictionary that uses values generated from another array in order to concatenate the name for said array/list/dictionary.


    Example of problem:

    I have a 2D array with the same 5 columns and 5000 rows dropped on my desk every 3 months.

    double [,] universeData = new double [5000, 5]
    {
    {conditionA, conditionB, conditionC, conditionD, column5}
    {…...}
    {…...}
    }

    I need to make sub groups of this 5000 item universe conditioned on the rankings from the 4 columns and then create sets from these sub groups that would encompass every conceivable combination of sub group items given the constraints. How can I set this up so I can easily iterate all the combinations?

    I can not use a multi dimensional array, because I don't always know the size of the column5 values in each sub group.

    Simplified example:
    Let's say I had 10 items and a conditionA and a column2.
    Create sets from these 10 items if I had 2 items in each set... 3, 4, 5, etc
    Find the average of each set.

    Now say you split the 10 items into 2 subgroups based on conditionA. Column2 data are the values in the array.

    SubGroupA0 = {.10, .05, -.07, .21, .18}
    SubGroupA1 = {.30, .12, .10, .03, -.15}

    Create sets from these 10 items if I had 2 items in each set AND 1 member in each subgroup A0 and A1. 4 items in each set and 2 in each subgroup. 6 items and 3 members in each etc.

    If I am splitting up the universe on just a single condition, I believe I can just make a 2D array [2,5] (as long as item count / subgroup count is a whole number) and then use a nested loop to make the sets of combinations. I always know the parameters of the array – [# of subgroups, array length/# of subgroups] or [2, 10/2]

    But let's add another condition, conditionB. Here lies the challenge.

    SubGroupA0B0 = {.10, .05}
    SubGroupA1B0 = {.10, .03, -.15}
    SubGroupA0B1 = { -.07, .21, .18}
    SubGroupA1B1 = {.30, .12}

    So, the length of the subgroup is dependent on the how the conditions interact with each other.

    In this case, I can't use a 3D array [# of sub groups conditionA ,# of sub groups conditionB, column3]
    double [,,] subGroup = new double {2, 2, unkown]

    Further, using Dictionary failed with subGroup as the Key Name.

    To further detail the example:
    The sub groups rankings are user defined and let's just say they chose to DECILE all 4 columns.
    The user can also choose to remove and then put back sub groups within the universe when doing computations later in the program. (Thus, a List would be ideal?)

    1) so in this case I believe there are 10,000 possible sub groups (10^4).
    2) subgroups may have have different number of records stored – from 0 to +/-500? (I think in this specific case)

    So run some code to find the relevant DECILE rank on the condition1 …thru condition4 columns.

    Say the the result for the first item of the 5000 items is:

    rankConditionA = 3 // 3 is the decile derived from code not shown
    rankConditionB = 0
    rankConditionC = 1
    rankConditionD = 8

    To me these 4 values define a sub group.

    string subGroup = '”'rankConditionA+rankConditionB+rankConditionC+rankConditionD'”'

    thus subGroup = “3018”

    Now within the universe of 5000 items I want to create subgroup arrays with unknown lengths (I think between 0 and 500) that store the value in Column5 of the array named by the above process. In this case "3018"

    A side note. I suppose the length could be known by sorting through the array with IF statements and counting each time 0000 or 0001 or 3018 appears. I am assuming this would be a ridiculous amount of IF code for 10,000 subgroups? Any other ways?

    – The sub group's [array/list name or dictionary key name] would be the “index” where values of Column 5 are stored.

    I can not use the following Dictionary code to load in the column5 values:

    for (int i=0; i<=universeData.GetUpperBound(0); i++)
    Dictionary <string, double> subGroupData = new Dictionary <sting, double>
    subGroupData.Add('”'+subGroup+'”', universeData[i, 4]);

    because the variable subGroup is not unique. That is, the first item's Dictionary Key Name is “3018” and maybe it turns out the fiftieth item's Key Name is too.

    So what about naming a List variable with resulting subGroup string value?

    Use the subGroup variable to declare a LIST named on the value in subGroup, that is now = 3018 in this loop, and then roll through in order to assign the column5 values.

    for (int j=0;j<5000;j++) //Loop through the 5000 items
    string subGroup = '”'rankConditionA+rankConditionB+rankConditionC+rankConditionD'”'
    List<double> [subGroup] = new List <double>(); //[subGroup] here represents its string value not a variable name
    [subGroup].Add(universeData[j, 4];


    So the idea would be access subGroup column5 values by its LIST variable name using nested loops of 10 (since the user chose to DECILE) for each conditionA/B/C/D to create the 10,000 possible subGroup List names that will call the column5 data.

    Note. The use of 10,000 List names maybe a nightmare to run the process to make the sets of combinations given the constraints.

    Thanks for looking at this. Peace. Tbone.

  2. #2
    Join Date
    Jan 2010
    Posts
    1,133

    Re: Noob Needs Direction - Dynamically Named Variables in C#

    If I understood you well, although subgroup IDs (keys) are not unique for elements, they are unique per subgroup, and you need to be able to dynamically change the number of elements for each subgroup, right?

    Try using Dictionary<string, List<double>> - this way you can have string IDs of the subgroups as keys and the subgroups themselves as elements (represented as List<double> lists).

  3. #3
    Arjay's Avatar
    Arjay is offline Moderator / EX MS MVP Power Poster
    Join Date
    Aug 2004
    Posts
    13,490

    Re: Noob Needs Direction - Dynamically Named Variables in C#

    Use TheGreatCthulhu's suggestion of a dictionary collection that contains a list. In general, in C#, you rarely ever want to have dynamic variable names (except for maybe client side web page scripting).

  4. #4
    Join Date
    Jul 2013
    Posts
    3

    Post Re: Noob Needs Direction - Dynamically Named Variables in C#

    Quote Originally Posted by Arjay View Post
    Use TheGreatCthulhu's suggestion of a dictionary collection that contains a list. In general, in C#, you rarely ever want to have dynamic variable names (except for maybe client side web page scripting).

    Hey thanks for the direction. I built a test code with a smaller data array [20,5] to test your suggestions.

    2 questions:
    1) Did I implement your suggestion properly? I'm not sure becuase I don't know how to print out the new data structure.
    2) What code do I write to print out the data structure of Dictionary<string, List<double>>
    2A) the second foreach loop does NOT compile..........................see it in bold and in red text

    "Error 1 foreach statement cannot operate on variables of type 'System.Collections.Generic.KeyValuePair<string,System.Collections.Generic.List<double>>' because 'System.Collections.Generic.KeyValuePair<string,System.Collections.Generic.List<double>>' does not contain a public definition for 'GetEnumerator' C:\Users\ProjectTurboCap\Desktop\Documents\Visual Studio 2012\Projects\NestedListConsole\NestedListConsole\Program.cs 91 17 NestedListConsole"

    2B) How do i find the length of the each Key Name's List<double> in order to run a for/loop? (I think I am using the correct lingo here?)

    Here is a copy of my program so far: Note data in column 0 and 1 of the original array are not used in this program. I had to do the indents by hand so there may be some oddness to the layout.

    ---- Your suggestion's code is BOLDED below.
    ---- The doomed foreach is red and bolded

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;

    namespace NestedListConsole
    {
    class Program
    {
    static void Main(string[] args)
    {
    //Load universeData for 20 items into a 2D array. Data is: NOT USED, NOT USED, Column3, Condition A, Condition B
    double[,] universeData = new double[20, 5]
    {
    {1.05, .891, .145, .10, .15},
    {2.21, 1.12, .211, .20, .35},
    {0.95, 1.01, .188, .05, .30},
    {4.23, 1.30, -.231, .55, .45},
    {6.33, 1.20, .103, .80, .40},
    {3.45, .901, .201, .50, .20},
    {1.34, 3.23, -.052,.15, .95},
    {2.22, 2.91, .329, .25, .90},
    {5.32, 1.45, .111, .65, .50},
    {9.46, 2.01, .190, 1.00, .80},
    {6.09, 1.90, .350, .70, .65},
    {3.02, .801, .289, .40, .10},
    {2.89, .999, .245, .30, .25},
    {6.45, 1.78, -.432, .85, .60},
    {2.90, .400, .321, .35, .05},
    {9.38, 4.87, .023, .95, 1.00},
    {3.43, 1.92, .177, .45, .70},
    {7.23, 2.02, .122, .90, .85},
    {4.55, 1.77, .324, .60, .55},
    {6.32, 1.99, -.033, .75, .75}
    };

    //Print out Data Array to confirm it copied in OK
    for (int i = 0; i <= universeData.GetUpperBound(0); i++) //altenatively its faster to use ;i < universeData.Length / 5; --- 5 here is the # of columns
    {
    double column3 = universeData[i, 2];
    double percentileConditionA = universeData[i, 3];
    double percentileConditionB = universeData[i, 4];

    Console.WriteLine("{0} {1} {2}", percentileConditionA, percentileConditionB, column3);
    }
    Console.ReadLine();

    //Define where the Categories ConditionA and CondtionB will be split : 1, 2, 4, 5, 10 .... quartile, quintile etc.....
    int splitConditionA = 1;
    int splitConditionB = 1;
    int categoryCount = splitConditionA * splitConditionB;

    Console.Write("Number of Condition A slices: ");
    splitConditionA = int.Parse(System.Console.ReadLine());
    Console.Write("Number of Condition B slices: ");
    splitConditionB = int.Parse(System.Console.ReadLine());

    //Determine which Slice the Category is in put it into a new data structure reflective of the slicing
    Dictionary<string, List<double>> categorySets = new Dictionary<string, List<double>>();
    double categoryDivisorA = 1 / Convert.ToDouble(splitConditionA);
    double categoryDivisorB = 1 / Convert.ToDouble(splitConditionB);
    string categoryNames;

    Console.WriteLine();
    for (int conditionA = 0; conditionA <= splitConditionA - 1; conditionA++) //Loops through number of CondtionA slices as input by the user
    {
    for (int conditionB = 0; conditionB <= splitConditionB - 1; conditionB++) //Loops through number of CondtionB slices as input by the user
    {
    categoryNames = '"' + conditionA.ToString() + conditionB.ToString() + '"';
    List<double> categoryColumn3 = new List<double>(); //Initiates a List which gets re-initiated upon building each conditoinal set
    for (int indexList = 0; indexList <= universeData.GetUpperBound(0); indexList++) //Loops though the items in universeData
    {
    double rankA = Math.Floor((universeData[indexList, 3] / categoryDivisorA) - .0001); //Finds which ConditionA bucket the element is placed given user choice
    double rankB = Math.Floor((universeData[indexList, 4] / categoryDivisorB) - .0001); //Finds which ConditionB bucket the element is placed given user choice
    if (rankA == conditionA & rankB == conditionB) //Compares the element's rank against the condition in order to add to the current List
    categoryColumn3.Add(universeData[indexList, 2]);
    }
    categorySets.Add('"' + categoryNames + '"', categoryColumn3); //Add the List to top level Dictionary with the Key Name being a concatenation of the
    //conditions used to create inner List
    }
    }
    Display(categorySets); //Calls Display() to display the data structure
    }
    static void Display(Dictionary<string, List<double>> data)
    {
    //Display the Dictionary
    foreach (var category in data)
    {
    Console.WriteLine(category);
    foreach (var item in category)
    {
    Console.WriteLine(item);
    }
    Console.WriteLine();
    }
    Console.WriteLine();
    Console.ReadLine();
    }
    }
    }

  5. #5
    Join Date
    Jul 2013
    Posts
    3

    Re: Noob Needs Direction - Dynamically Named Variables in C#

    Hello. I sent a nicely worded and indented reply with bolds and colored text. Have no clue where it posted. I am reposting.

    Thanks for your direction. I built some test code to try out your suggestion. I have 2 quetions:

    1) Did I implement your suggestion properly? I don't know because I can't print out the new data structure.
    2) How do you print out the new stucture?
    2A) the second foreach would NOT compile ...............

    Error 1 foreach statement cannot operate on variables of type 'System.Collections.Generic.KeyValuePair<string,System.Collections.Generic.List<double>>' because 'System.Collections.Generic.KeyValuePair<string,System.Collections.Generic.List<double>>' does not contain a public definition for 'GetEnumerator' C:\Users\ProjectTurboCap\Desktop\Documents\Visual Studio 2012\Projects\NestedListConsole\NestedListConsole\Program.cs 91 17 NestedListConsole


    2B) I don't know how the find the lenght of DIctionary(string, List<double>>) in order to for/loop.

    Thanks again for your help.

    Here is a copy if my code.

    Code:
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace NestedListConsole
    {
        class Program
        {
            static void Main(string[] args)
            {
                //Load universeData for 20 items into a 2D array.   Data is: NOT USED,  NOT USED, Column3, Condition A, Condition B
                double[,] universeData = new double[20, 5]
                {
                    {1.05, .891, .145, .10, .15},
                    {2.21, 1.12, .211, .20, .35},
                    {0.95, 1.01, .188, .05, .30},
                    {4.23, 1.30, -.231, .55, .45},
                    {6.33, 1.20, .103, .80, .40},
                    {3.45, .901, .201, .50, .20},
                    {1.34, 3.23, -.052,.15, .95},
                    {2.22, 2.91, .329, .25, .90},
                    {5.32, 1.45, .111, .65, .50},
                    {9.46, 2.01, .190, 1.00, .80},
                    {6.09, 1.90, .350, .70, .65},
                    {3.02, .801, .289, .40, .10},
                    {2.89, .999, .245, .30, .25},
                    {6.45, 1.78, -.432, .85, .60},
                    {2.90, .400, .321, .35, .05},
                    {9.38, 4.87, .023, .95, 1.00},
                    {3.43, 1.92, .177, .45, .70},
                    {7.23, 2.02, .122, .90, .85},
                    {4.55, 1.77, .324, .60, .55},
                    {6.32, 1.99, -.033, .75, .75}
                };
    
                //Print out Data Array to confirm it copied in OK
                for (int i = 0; i <= universeData.GetUpperBound(0); i++)		//altenatively its faster to use ;i < universeData.Length / 5; --- 5 here is the # of columns
                {
                    double column3 = universeData[i, 2];
                    double percentileConditionA = universeData[i, 3];
                    double percentileConditionB = universeData[i, 4];
    
                    Console.WriteLine("{0} {1} {2}", percentileConditionA, percentileConditionB, column3);
                }
                Console.ReadLine();
    
                //Define where the Categories ConditionA and CondtionB will be split : 1, 2, 4, 5, 10 .... quartile, quintile etc.....
                int splitConditionA = 1;
                int splitConditionB = 1;
                int categoryCount = splitConditionA * splitConditionB;
    
                Console.Write("Number of Condition A slices: ");
                splitConditionA = int.Parse(System.Console.ReadLine());
                Console.Write("Number of Condition B slices: ");
                splitConditionB = int.Parse(System.Console.ReadLine());
    
                //Determine which Slice the Category is in put it into a new data structure reflective of the slicing
                Dictionary<string, List<double>> categorySets = new Dictionary<string, List<double>>();
                double categoryDivisorA = 1 / Convert.ToDouble(splitConditionA);
                double categoryDivisorB = 1 / Convert.ToDouble(splitConditionB);
                string categoryNames;
    
                Console.WriteLine();
                for (int conditionA = 0; conditionA <= splitConditionA - 1; conditionA++)                 //Loops through number of CondtionA slices as input by the user  
                {
                    for (int conditionB = 0; conditionB <= splitConditionB - 1; conditionB++)                 //Loops through number of CondtionB slices as input by the user  
                    {
                        categoryNames = '"' + conditionA.ToString() + conditionB.ToString() + '"';
                        List<double> categoryColumn3 = new List<double>();                                                    //Initiates a List which gets re-initiated upon building each conditoinal set
                        for (int indexList = 0; indexList <= universeData.GetUpperBound(0); indexList++)            //Loops though the items in universeData
                        {
                            double rankA = Math.Floor((universeData[indexList, 3] / categoryDivisorA) - .0001);     //Finds which ConditionA bucket the element is placed given user choice
                            double rankB = Math.Floor((universeData[indexList, 4] / categoryDivisorB) - .0001);     //Finds which ConditionB bucket the element is placed given user choice
                            if (rankA == conditionA & rankB == conditionB)        			                 	     //Compares the element's rank against the condition in order to add to the current List
                                categoryColumn3.Add(universeData[indexList, 2]);
                        }
                        categorySets.Add('"' + categoryNames + '"', categoryColumn3);                                      //Add the List to top level Dictionary with the Key Name being a concatenation of the 
                                                                                                                                                         //conditions used to create inner List
                    }                
                }
                Display(categorySets);                                                                      //Calls Display() to display the data structure
            }        
            static void Display(Dictionary<string, List<double>> data)
            {
                //Display the Dictionary
                foreach (var category in data)
                {
                    Console.WriteLine(category);
                    foreach (var item in category)
                    {
                        Console.WriteLine(item);
                    }
                    Console.WriteLine();
                }
                Console.WriteLine();
                Console.ReadLine();
            }
        }
    }
    Last edited by BioPhysEngr; July 23rd, 2013 at 10:40 PM.

  6. #6
    Join Date
    Feb 2011
    Location
    United States
    Posts
    1,016

    Re: Noob Needs Direction - Dynamically Named Variables in C#

    You'll want to use [code] and [/code] tags around your code to keep formatting; I've updated your reply with them.
    Best Regards,

    BioPhysEngr
    http://blog.biophysengr.net
    --
    All advice is offered in good faith only. You are ultimately responsible for effects of your programs and the integrity of the machines they run on.

  7. #7
    Join Date
    Feb 2011
    Location
    United States
    Posts
    1,016

    Re: Noob Needs Direction - Dynamically Named Variables in C#

    Just replying to a small part:

    You are having trouble printing the Dictionary. You should try it like this:

    Code:
    static void Display(Dictionary<string, List<double>> data)
    {
    	//Display the Dictionary
    	foreach (string category in data.Keys)
    	{
    		Console.WriteLine(category);
    		List<double> catList = data[category];
    		foreach (double item in catList)
    		{
    			Console.WriteLine(item);
    		}
    		Console.WriteLine();
    	}
    	Console.WriteLine();
    	Console.ReadLine();
    }
    Didn't debug (but should be free of syntax errors I think). The idea is to iterate through the set of keys in the dictionary.

    Also, whenever possible, avoid use of var if the type is known (as it is here).
    Best Regards,

    BioPhysEngr
    http://blog.biophysengr.net
    --
    All advice is offered in good faith only. You are ultimately responsible for effects of your programs and the integrity of the machines they run on.

  8. #8
    Arjay's Avatar
    Arjay is offline Moderator / EX MS MVP Power Poster
    Join Date
    Aug 2004
    Posts
    13,490

    Re: Noob Needs Direction - Dynamically Named Variables in C#

    Quote Originally Posted by BioPhysEngr View Post
    Also, whenever possible, avoid use of var if the type is known (as it is here).
    Respectfully, I disagree. Coming from a strongly typed language background (C++), I found the use of var a bit hard to get used to because it first seemed too 'scripty'. Then I got used to it and it really makes the code less cluttered (IMO). It is different than the old styled VB or scripting because var in C# is type safe.

    To me,

    Code:
    var data = Dictionary<string, List<double>>();
    
    //Display the Dictionary
    foreach (var category in data.Keys)
    {
      Console.WriteLine(category);
      var catList = data[category];
      
      foreach (var item in catList)
      {
        Console.WriteLine(item);
      }
    }
    Is way more cleaner than explictly declaring the variables. Even tools like Resharper now suggest using var and C++ has the same sugar too.

  9. #9
    Join Date
    Jan 2010
    Posts
    1,133

    Re: Noob Needs Direction - Dynamically Named Variables in C#

    Ok, I went through your code and I think I see what you are trying to do, but you are making it more complicated than it needs to be, I think.

    In essence, you have a 2D array of inputs which basally models a table of data.
    In each row there are some conditions and the actual data of interest. The data is to be used to form several sets (cathegories) by using it as input for each cathegory and then dividing it into "buckets" of equal sizes (quarticles, quinticles, etc...), as defined for that particular cathegory.
    The user enters a number of slices (buckets) for each category, and in this context, the conditions in the original table actually specify into which slice (bucket) the actual data from that row goes, for a given cathegory (so, the condition-columns themselves represent individual categories, and the corresponding condition values are really bucked IDs for that column).

    What you want to do is to take all this input and use it to create a bunch of new sets (let's call them "classes" - not in the sense of C# class, but class as in "classification" - a group of related things) where all elements in a given set ("class") have the same combination of conditions (bucket IDs for each cathegory). So, each "class" is determined by the specific combination of conditions, and each contains a variable number of our actual data elements.

    Something along these lines (note that I allowed for the possibility that the input is incomplete - there could be less rows then there are possible buckets and bucket cobinations):
    Code:
    | BucketID_for_A | BucketID_for_B | ActualData |
    |      2         |        5       |     a      |             Classes:
    |      4         |        1       |     b      |    --->     "2, 5" = {a, c}
    |      2         |        5       |     c      |             "4, 1" = {b}
    |      3         |        2       |     d      |             "3, 2" = {d}
    Am I right so far?


    So, a few tips. For a general input, not all possible buckets or combinations of buckets ("classes") will contain elements - some of them will be empty. You should take advantage of this - it will greatly reduce your memory footprint. You only need to store those "classes" that are non-empty - and with dictionaries you can do this. The key identifies the "class", and if the value (list) stored at that key exist, the "class" is non empty, if it doesn't, you just return information indicating that it is (conceptually) empty.

    Furthermore, take a close look at the input data 2d array (a.k.a table): for each actual data entry, tbe combination of the bucket IDs is already specified in that row; each data entry has a "class" already associated with it, so you don't have to actually compute anything.

    This | 2 | 5 | a |
    directly translates to this:
    a is element of "2, 5"

    All this considered, you don't have to keep track of the # of "classes", total number of elements, etc. The Dictionary and List C# classes do all this for you.

    So, let me revise the code you posted above:
    Code:
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace NestedListConsole
    {
        class Program
        {
            // Let me first define some descriptive constants so we don't have to remember
            // which index is for what, etc.
            
            // these relate directly to your universeData table below
            public const int ActualDataIndex = 2;   // previously Column3
            public const int BucketIdAIndex = 3;    // previously Condition A
            public const int BucketIdBIndex = 4;    // previously Condition B
        
            static void Main(string[] args)
            {
                //Load universeData for 20 items into a 2D array.   Data is: NOT USED,  NOT USED, relevant data, BucketID for A , Bucket ID for B
                double[,] universeData = new double[20, 5]
                {
                    {1.05, .891, .145, .10, .15},
                    {2.21, 1.12, .211, .20, .35},
                    {0.95, 1.01, .188, .05, .30},
                    {4.23, 1.30, -.231, .55, .45},
                    {6.33, 1.20, .103, .80, .40},
                    {3.45, .901, .201, .50, .20},
                    {1.34, 3.23, -.052,.15, .95},
                    {2.22, 2.91, .329, .25, .90},
                    {5.32, 1.45, .111, .65, .50},
                    {9.46, 2.01, .190, 1.00, .80},
                    {6.09, 1.90, .350, .70, .65},
                    {3.02, .801, .289, .40, .10},
                    {2.89, .999, .245, .30, .25},
                    {6.45, 1.78, -.432, .85, .60},
                    {2.90, .400, .321, .35, .05},
                    {9.38, 4.87, .023, .95, 1.00},
                    {3.43, 1.92, .177, .45, .70},
                    {7.23, 2.02, .122, .90, .85},
                    {4.55, 1.77, .324, .60, .55},
                    {6.32, 1.99, -.033, .75, .75}
                };
    
                //Print out Data Array to confirm it copied in OK
                // NOTE: Quote "altenatively its faster to use ;i < universeData.Length / 5; --- 5 here is the # of columns"
                // Not necessarily - in release mode the compiler will probably optimise the loop header
                // The biggest slowdown here comes from Console.WriteLine() call at the bottom
                for (int row = 0; row <= universeData.GetUpperBound(0); row++)	// note: I changed "i" to "row"
                {
                    // using descriptive constants and variable names makes it easier to see what the code does
                    // and easier to change the code later, if required
                    double column3 = universeData[row, ActualDataIndex];
                    double percentileConditionA = universeData[row, BucketIdAIndex];
                    double percentileConditionB = universeData[row, BucketIdBIndex];
    
                    Console.WriteLine("{0} {1} {2}", percentileConditionA, percentileConditionB, column3);
                }
                Console.ReadLine();
    
                // Given what I said in the post above, you won't actually need any of these:
                
                /*
                //Define where the Categories ConditionA and CondtionB will be split : 1, 2, 4, 5, 10 .... quartile, quintile etc.....
                int splitConditionA = 1;
                int splitConditionB = 1;
                
                //int categoryCount = splitConditionA * splitConditionB;  // WRONG: this will allways remain 1
                // P.S. You don't use cathegoryCount anyway
    
                
                
                Console.Write("Number of cathegory A buckets: ");        // was: Number of Condition A slices
                splitConditionA = int.Parse(System.Console.ReadLine());
                
                Console.Write("Number of cathegory B buckets: ");        // was: Number of Condition B slices
                splitConditionB = int.Parse(System.Console.ReadLine());
                */
                
                
                // HERE'S THE FUN PART
                
                // First, create a dictionary to hold your "classes" (with their elements):
                Dictionary<string, List<double>> dataClasses = new Dictionary<string, List<double>>();
                
                // Now iterate through your 2D array as before:
                for (int row = 0; row <= universeData.GetUpperBound(0); row++)
                {
                    double data = universeData[row, ActualDataIndex];
                    double bucketIdForA = universeData[row, BucketIdAIndex];
                    double bucketIdForB = universeData[row, BucketIdBIndex];
    
                    // Combine bucketIDs to get the key for each "class"
                    // Simple string concatenation will suffice
                    string classID = bucketIdForA.ToString() + "; " + bucketIdForB.ToString();
                    
                    // Check if the dataClasses dictionary DOES NOT contain the key:
                    if (!dataClasses.ContainsKey(classID))
                    {
                        // OK, add a list to that key
                        dataClasses[classID] = new List<double>();
                    }
                    
                    // (otherwise, the key exists and has an associated list)
                    
                    // Now that we made sure that a list exist at that key, we can add our data:
                    // (1) Get the list at the given key
                    List<double> dataItems = dataClasses[classID];
                    
                    // (2) add the data value to it
                    dataItems.Add(data);
                }
                
                // Construction DONE!
                
                // To check, use BioPhysEngr's code:
                Display(dataClasses);
                
                // ALL DONE
            }
            
            static void Display(Dictionary<string, List<double>> dataClasses)
            {
                //Display the Dictionary
                foreach (string dataClassID in dataClasses.Keys)
                {
                    Console.WriteLine("\"" + dataClassID + "\"");
                    
                    List<double> dataItems = dataClasses[dataClassID];
                    foreach (double item in dataItems)
                    {
                        Console.WriteLine(item);
                    }
                    Console.WriteLine();
                }
                Console.WriteLine();
                Console.ReadLine();
            }
        
        }    
    }
    So basically, what you have here is a Dictionary object which represents a collection of your "classes", each of them identified by a key. The lists associated with each key store the actual data elements for a given "class".

    Is this close enough to what you intended, or did I get it significantly wrong?
    P.S. I didn't actually run this code, but if any errors pop-up, I think you'll be able to figure them out.

    P.P.S. A few more tips:
    I kicked this out of your code, but generally speaking - you can make something like this more readable by making the integer numerical literal be a double instead:

    double categoryDivisorA = 1 / Convert.ToDouble(splitConditionA);

    vs

    double categoryDivisorA = 1.0 / splitConditionA;
    Last edited by TheGreatCthulhu; July 24th, 2013 at 12:46 PM.

  10. #10
    Join Date
    Jan 2010
    Posts
    1,133

    Re: Noob Needs Direction - Dynamically Named Variables in C#

    About var:

    I think a good general guideline is: use it if it helps avoid needless repetition.
    As in:

    var aDictionary = new Dictionary<string, List<DataItems>>();

    vs

    Dictionary<string, List<DataItems>> aDictionary = new Dictionary<string, List<DataItems>>();

    But I also wouldn't say I disagree with Arjay - sometimes, often in code that utilizes foreach loops, you don't really care about the actual types, you're more concerned with what happens in terms of application logic. For example, I often don't care what the types of the object containers are, but when I come down to the manipulating the data stored in them, I prefer to explicitly state the type, rather than use var, unless it's something trivial.

    I suppose it's up to the judgement of the coder in a particular situation (or the coding standards of the team/company).

  11. #11
    Join Date
    Jan 2010
    Posts
    1,133

    Re: Noob Needs Direction - Dynamically Named Variables in C#

    Tested the code - it runs, and produces the output I expected, but I can't be sure if that is what you wanted.
    It occurred to me that it is possible that the "conditions" require some sort of processing, but you should be able to easily plug that into the above code, right before the line where the "classID" string is created.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured