3

I need to add item to a dictionary while reading data from a text file. I want that for every line I will have x data from this particular line in my array. So I declare one two-dimensional array in my class:

Contactsp = new string[][] { };

int number = 0;

using the dictionary:

Dictionary<string, Contact> dict = new Dictionary<string, Contact>();

readin from the file:

foreach (var line in File.ReadAllLines(fileName).Where(l =!string.IsNullOrWhiteSpace(l)))
{
    for (int j = 0; j < line.Length; j++)
    {             
        for (int i = 0; i < line.Length; i += 9)
        {            
            string hexText = line.Substring(i, 9);
            string c       = hexText.Substring((hexText.Length - 2));
            int length     = Convert.ToInt32(c, 16);
            Char[] B       = new char[length];
            string key     = line.Substring(i, 4);
            string value   = line.Substring(i + 9, length);
            i += length;

            if (!dict.TryGetValue(key, out myContact))
            {
                myContact = new Contact();
                // didn't find a record for this key, so add a new one
                dict.Add(key, myContact);
            }
            dict[key].Contactsp[j][dict[key].number++] = value;  
         }
         j++;
    }
}

while running it I am getting the exception of "System.IndexOutOfRangeException" on the line dict[key].Contactsp[j][dict[key].number++] = value;

Why?

AustinWBryan
  • 3,249
  • 3
  • 24
  • 42
Monika
  • 55
  • 11
  • you haven't set length of your 2D array at initialization. so it length will be 0. and now you are trying to set value of at some index (which is Out of array's Range) – Amit Jun 04 '18 at 04:29
  • I see no evidence of you initializing the array `dict[key].Contactsp`. Also, you need to initialize each dimension of your array (so in `items[][]`, `item[0]` has a 1d array, etc.) – ProgrammingLlama Jun 04 '18 at 04:32
  • @Amit I want it to set dynamically so if I have on line number 1- 3 items and on the next line 2 items it will be fine – Monika Jun 04 '18 at 04:34
  • @john thanks. how can I initialize it dynamically? – Monika Jun 04 '18 at 04:35
  • 1
    @Monika If you want to set it's length dynamically, array is not good choice for you. may be `List>` – Amit Jun 04 '18 at 04:35
  • @Amit then how I update the value? so it will be the same like: dict[key].Contactsp[j][dict[key].number++] = value; – Monika Jun 04 '18 at 04:36
  • @Monika, see you can never get value from some index (whether it is array or list) if you haven't set the value at that index (if length is given at declaration, value will be default as per type). you can always check if whatever index you are fetching is exist in your collection by checking `if(count > index)` logic – Amit Jun 04 '18 at 04:39
  • @john maybe you? – Monika Jun 04 '18 at 04:39
  • @Amit I know that there are 4 line on the text file. but I don't know how many values from each line have to be inserted – Monika Jun 04 '18 at 04:41
  • @Monika making length of collection is totally fine. you just need to check of valid index while setting/getting data into/from collection. putting an answer. try it out and let me know if it works for you – Amit Jun 04 '18 at 04:42
  • @Amit ok, after checking how to update the value to List>? – Monika Jun 04 '18 at 04:43
  • @Monika i have put an answer here. try it out – Amit Jun 04 '18 at 04:50
  • Why are you calling `j++` twice? Couldn't you just do `j += 2` once at the top of the loop? – AustinWBryan Jun 04 '18 at 05:50

2 Answers2

0

With Contactsp = new string[][] { }; you create a fixed size array (this code is the same like new string[0][0]). If you need a dictionary, just use Dictionary<TKey, TValue>:

var contactsp = new Dictionary<int, int>();
vasily.sib
  • 3,871
  • 2
  • 23
  • 26
  • I created a also a dictionary Dictionary dict = new Dictionary(); – Monika Jun 04 '18 at 04:30
  • 1
    @vasily he does have Dictionary, and in value of that dictionary he has some object (as mention above `Contact`) with 2D array as property. – Amit Jun 04 '18 at 04:30
  • what i mean, is that after you write this: `Contactsp = new string[][] { };` you now **can't** add anything to Contactsp, because it is **fixed-sized**. – vasily.sib Jun 04 '18 at 04:42
  • @vasily.sib and if I know that I have to read 4 lines from each one different number of items? Contactsp = new string[4][] { };? – Monika Jun 04 '18 at 04:47
  • @vasily.sib while install Contactsp = new string[4][]; I am getting the exception of System.NullReferenceException – Monika Jun 04 '18 at 04:51
  • 1
    @Monika your second demension is still **fixed-sized**, so you still can't add anything to this. Why don't you just use Dictionary? – vasily.sib Jun 04 '18 at 04:54
  • @vasily.sib because I have more then 1 item to each key – Monika Jun 04 '18 at 04:59
  • @Monika `new Dictionary>`? Or even `new List[4]`? – vasily.sib Jun 04 '18 at 07:48
0

As per our discussion, here i m posting a logic, try it out. in your Contact class, there should be a List which will hold data of every person.

So ultimate data structure is, Dictionary<string, Contact> data = new Dictionary<string, Contact>();

foreach (var line in File.ReadAllLines(fileName).Where(l => !string.IsNullOrWhiteSpace(l)))
{
    if (lineNum >= 4)
        break;

    string line = lines[lineNum];

    for (int i = 0; i < line.Length; )
    {
        string key = line.Substring(i, 4);
        string hexText = line.Substring(i, 9);
        int length = Convert.ToInt16(hexText.Substring(hexText.Length - 2), 16);

        string value = line.Substring(i + 9, length);

        if (lineNum == 3)
            value = FromUnixTime(Convert.ToInt64(value)).ToString();

        if (data.ContainsKey(key))
        {
            data[key].ContactSp.Add(value);
        }
        else
        {
            Contact c = new Contact();
            c.ContactSp.Add(value);
            data.Add(key, c);
        }
        i = i + 9 + length;
    }
}

To convert date time, you will need this method, (see this question)

public static DateTime FromUnixTime(long unixTime)
{
    return epoch.AddSeconds(unixTime);
}
private static readonly DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);

and if you want to print all values (for debug)

//and to print all values
foreach(string code in data.Keys)
{
    Console.WriteLine("For Code: " + code);
    foreach(string value in data[code].ContactSp)
    {
        Console.WriteLine("     " + value);
    }
}
Amit
  • 1,821
  • 1
  • 17
  • 30
  • thank you so much. but when I am ruining it I am getting System.ArgumentOutOfRange Exception on the line Contactsp[Contactsp.Count].Add(value); – Monika Jun 04 '18 at 05:11
  • @Monika yes i mis-wrote that.. that should be `Contactsp.Count - 1`, as `.Count` property gives us count of elements in collection, while last element in the collection (as indexing is 0 based) will be at `count - 1` only. – Amit Jun 04 '18 at 05:15
  • Thank you so mush! but now I have the same value twice..I mean also on Contactsp[0] and Contactsp[1] – Monika Jun 04 '18 at 05:20
  • I mean the same string in different cells. maybe I am reading the same line twice and the condition not getting there is already the same value? @Amit – Monika Jun 04 '18 at 05:32
  • how can I add screenshot? – Monika Jun 04 '18 at 05:34
  • in your question edit box, you will see an icon of image beside `{ }` icon – Amit Jun 04 '18 at 05:35
  • @Monika no, currently condition is not checking that, tell me exact what checking should be done while adding elements in list, we can edit answer as per that. **But you too need to do some debugging** – Amit Jun 04 '18 at 05:37
  • @Monika yes it seems you are looping extra. you have three loops while I guess, reading 2D array should require only two loops . and also in loop of `j` you are incrementing `j` twice (`j++` and `j+=1`), you sure about that? and same of `i` loop – Amit Jun 04 '18 at 05:41
  • Thank you. sure-I will do. I want that if the value is exist in the dict[key] add to the dict[key] element on the list. i mean that if key 123 is exsict on the dict with Contactsp.[o] = olga, the next string with that key will be on Contactsp.[1] – Monika Jun 04 '18 at 05:42
  • You are right. Actually I don't need j. I have foreach (var line in File.ReadAllLines(fileName).Where(l => !string.IsNullOrWhiteSpace(l))) to read the text. – Monika Jun 04 '18 at 05:44
  • I did j to be the number of the lines.. Do you think that I can insert the list without it? – Monika Jun 04 '18 at 05:47
  • @Monika In that context, I afraid that I'm not completely aware about your requirement and also not sure about how data looks like in your file. so without that i will not able to answer your this question.! Sorry. – Amit Jun 04 '18 at 05:50
  • You are right, it wasn't clear enough. the propose of the int number and the array were - if you getting a key put the value in place number ++ of the array. that way if you get value with already exist key you put the value on array[1] and not array [0] and new key on array[0] that is the story. I want to do it with List>. please. thank you so much – Monika Jun 04 '18 at 06:14
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/172379/discussion-between-amit-and-monika). – Amit Jun 04 '18 at 07:11
  • @Monika So let me understand first, there is a file with multiple lines init. you want one entry per line in dictionary. here first 4 letters of line should be key of dictionary and remaining letters should be stored in "myContact" object in List> properly ? meaning, if for one key there may two entries , it should be stored in the same key of dictionary but as different entries of List> ? – Amit Jun 04 '18 at 07:23