C # 4.0 - Multidimensional associative array (or a way to simulate one?)

I am an experienced PHP developer moving to C #. I am currently working on a Windows Forms application.

In my searches, I found that C # does not support associative arrays in the same way as PHP. I found information about the dictionary and something about the "structures" that appear to be class objects.

I'm having a problem not only with an associative array, but also with a multidimensional one, which I want to use to store several counters in a series of loops.

The application reads a text log file, looks for a predetermined line, draws a date in this line when a line is detected, and increments the counter for this line in that date.

In PHP, it would be so simple:

// Initialize $count_array[$string_date][$string_keyword] = 0; ... // if string is found $count_array[$string_date][$string_keyword] += 1; ... // To ouput contents of array foreach($count_array as $date -> $keyword_count_array) { echo $date; // output date foreach($keyword_count_array as $keyword -> $count) { echo $keyword . ": " . $count; } } 

It seems to be a bit more involved in C # (which is not so bad). I tried using a sentence that I found on another similar question, but I really do not follow how to either increase or iterate / output the content:

 // Initialize var count_array = new Dictionary<string, Dictionary<string, int>>(); count_array = null; ... // if string is found - I think the second reference is supposed to be a Dictionary object?? count_array[string_date.ToShortDateString()][string_keyword]++; ... // To ouput contents of "array" foreach (KeyValuePair<string, Dictionary<string, int>> kvp in exportArray) { foreach(KeyValuePair<string, int> kvp2 in kvp.Value) { MessageBox.Show(kvp.Key + " - " + kvp2.Key + " = " + kvp2.Value); } } 

Am I even on the right track? Or does anyone have a better / cleaner method of spoofing PHP code above?

UPDATE

With the above C # code, I really get an error message in the string "// if string found". Error: "The object reference is not installed on the object instance." I assume this is because I have a line in a reference article, not in a dictionary. So right now I'm not sure how to grow.

UPDATE 2

Thank you all for your time. The current code now functions thanks to an understanding of how the dictionary works. However, all advice regarding the use of classes and objects for this situation is also not lost. I can reorganize to satisfy.

+6
c # associative-array multidimensional-array
source share
6 answers

The code itself looks healthy, the only thing I see is missing is there are no checks to see if the values ​​exist before they are incremented.

Before calling

 count_array[string_date.ToShortDateString()][string_keyword]++; 

You will need to do:

 string shortDate = string_date.ToShortDateString(); if (!count_array.ContainsKey(shortDate)) { count_array.Add(shortDate, new Dictionary<string, int>()); } if (!count_array[shortDate].ContainsKey(string_keyword)) { count_array[shortDate].Add(string_keyword, 0); } 

Before you try to increase anything.

You need to initialize the vocabulary by calling .Add or ["key"] = value. A call to ++ on an uninitialized dictionary entry will not work. Depending on what exactly you are trying to accomplish, although it might be a good idea to use a class.

+4
source share

You can use a tuple to create a multidimensional key for use in a dictionary.

 Dictionary<Tuple<TKey1,TKey2>,TValue> 

Or dictionary dictionary:

 Dictionary<TKey1,Dictionart<TKey2,Tvalue>> 

The second one is more annoying to work with, but has a growth potential that can only be indexed into it using the first key, and then get all the key-value pairs associated with this key.

But maybe you can use some linq, but your code is a bit incomplete for this.

+2
source share

How to create a class for this?

 public class LogEntry { private List<int> _lines = new List<int>(); public string LogContent { get;set; } public DateTime Time { get;set; } public List<int> Lines { get { return _lines; } } } 

Do you still have a dictionary, probably DateTime, LogEntry? Not quite sure what exactly you need / what the key is.

In any case, creating a class seems "right", as you can express your intention more clearly.

+1
source share

Your approach may work, however, you should understand that the Dictionary is a reference type, which means that it must be created before use. You are creating a "top level" dictionary, but "second level" dictionaries must also be created. But in

 count_array[string_date.ToShortDateString()][string_keyword]++; 

you think that count_array[string_date.ToShortDateString()] has already been created (so that it can be requested). And another problem is that the behavior of Dictionary<Key, Value> is that attempting to access an element that does not exist results in an exception ( KeyNotFoundException ). There is a milder TryGetValue method. In combination, you need to do something in accordance with:

 // Initialize var count_array = new Dictionary<string, Dictionary<string, int>>(); // if string is found - I think the second reference is supposed to be a Dictionary object?? Dictionary<string, int> perDateDict; var dateKey = string_date.ToShortDateString(); if (!count_array.TryGetValue(dateKey, out perDateDict) { perDateDict = new Dictionary<string, int>(); count_array.Add(adteKey, perDateDict); } int prevValue; // note that when not found, prevValue will be zero, which is what we need perDateDict.TryGetValue(string_keyword, out prevValue); perDateDict[string_keyword] = prevValue+1; // To ouput contents of "array" foreach (KeyValuePair<string, Dictionary<string, int>> kvp in exportArray) { foreach(KeyValuePair<string, int> kvp2 in kvp.Value) { MessageBox.Show(kvp.Key + " - " + kvp2.Key + " = " + kvp2.Value); } } 
0
source share

One thing, you must be sure that the dictionary is not a ValueType and is not initialized automatically.

Therefore, when you say that count_array = null, it means that you are returning a reference to a null location. Just delete the line.

Your code should look like this:

  var count_array = new Dictionary<string, Dictionary<string, int>>(); // if string is found - I think the second reference is supposed to be a Dictionary object?? string dt = DateTime.Now.ToShortDateString(); count_array[dt] = new Dictionary<string, int>(); //It is important as you should always give appropriate refernece before doing a fetch. count_array[dt]["key"] = 0; //Value types are defaults to 0 so it is not explicitely required. //Now you can do count_array[dt]["key"]++; // To ouput contents of "array" foreach (KeyValuePair<string, Dictionary<string, int>> kvp in count_array) { foreach (KeyValuePair<string, int> kvp2 in kvp.Value) { Console.WriteLine(kvp.Key + " - " + kvp2.Key + " = " + kvp2.Value); } } 

Can you also use? to ensure that when the Dictionary is zero, you assign a new link.

count_array [dt] = count_array [dt] ?? new dictionary ();

Hope this helps you even if you need to transcode it correctly.

0
source share

You need to start thinking about OO terms. In the production code, I would assign the classes an assignment for the assignment, instead of directly navigating to the Console, and perhaps use a strategy or similar form to format the text, but essentially it's an OO way of thinking about the problem.

 class Log { Dictionary<DateTime, List<LogEntry>} Entries { get; private set; } public void PrintLogs() { foreach (var date in Entries.Keys) { Console.WriteLine(date); foreach (var entry in Entries[date]) { entry.PrintEntry(); } } } } class LogEntry { public List<string> EntryLines { get; set; } public DateTime Date { get; set; } public void PrintEntry() { foreach (var line in EntryLines) Console.WriteLine(line); } } 
0
source share

All Articles