Cato
Cato

Reputation: 31

Inserting the first value of a key-value pair, when the value is a list

I have a dictionary as below, where the key is a string and the value is a list of doubles:

Dictionary<string, List<double>> dataStore = new Dictionary<string, List<double>>();
List<string> channel_names = new List<string>(); // contains the keys

Now when I want to add data to this dictionary, I do:

if (dataStore.ContainsKey(channel_names[j]))
{
    dataStore[channel_names[j]].Add(measurement);
}
                            
else
{
    dataStore.Add(channel_names[j], new List<double>((int)measurement));
}

The first statement (adding to an existing key) works fine, but something is wrong with the second statement, i.e. when I am trying to initialise the keys with the first double in the list. The first measurement is being missed out. Can anyone please advise as to why?

Thanks

Upvotes: 0

Views: 586

Answers (6)

Dmitrii Bychenko
Dmitrii Bychenko

Reputation: 186668

You have two alternatives:

  1. If you have list for given key, just add measurement to the existing value (which is list)
  2. If dataStore doesn't have the key, you should add entire key-value pair: key (channel_names[j]) and value which is list with one item

Code:

if (dataStore.TryGetValue(channel_names[j], out var list))
  // the key exists; just add measurement to the existing list
  list.Add(measurement);
else
  // no key found; add key-value pair: key and a list with one item 
  dataStore.Add(channel_names[j], new List<double>() {measurement});

Upvotes: 1

Joshua Robinson
Joshua Robinson

Reputation: 3539

The constructor on List<T> which takes an integer is not adding that integer to the list. It is setting the capacity of the list.

Instead you could use an initializer...

dataStore.Add(channel_names[j], new List<double>() { measurement };

Alternatively, you could use Dictionary.TryGetValue to find the List<double> for the given string, add it if it doesn't exist, then just modify it.

List<double> values = null;
if (!dataStore.TryGetValue(channel_names[j], out values))
{
   values = new List<double>();
   dataStore.Add(channel_names[j], values);
}
values.Add(measurement);

Upvotes: 0

MakePeaceGreatAgain
MakePeaceGreatAgain

Reputation: 37000

There are two constructors for List<T> that do different things.

When you call new List<T>(int) you create a new list of the provided size - or more exact the initial capacity of that list.

When you want to create and fill a new list in one go, you should use a collection-initializer:

dataStore.Add(channel_names[j], new List<double> { measurement });

As an asside you can simplify your code:

if (!dataStore.ContainsKey(channel_names[j]))
{
    dataStore[channel_names[j]] = new List<int>();
}                                
dataStore[channel_names[j]].Add(measurement);

Upvotes: 2

Flydog57
Flydog57

Reputation: 7111

As I mention in the comments and others have mentioned, you aren't adding things to the list when you construct it, you are allocating capacity to the list. The code you want is:

if (!dataStore.ContainsKey(channel_names[j]))
{
    dataStore.Add(channel_names[j], new List<double>();
}
dataStore[channel_names[j]].Add(measurement);

If the Dictionary doesn't contain the key you want, you create a new list and add it to the dictionary. At this point, the dictionary necessarily contains the appropriate key (it either already existed and you skipped the if block, or it didn't exist and you created it). In any case, at that point, you can just add the measurement to the appropriate list.

Upvotes: 1

Johnathan Barclay
Johnathan Barclay

Reputation: 20354

You are using the constructor List(int), where int specifies the initial capacity of the list; it does not add that number to the list.

You could instead use collection-initialiser syntax:

new List<double> { measurement }

Upvotes: 5

SomeBody
SomeBody

Reputation: 8743

You can refactor your code to this solution:

if (!dataStore.ContainsKey(channel_names[j]))
{
    dataStore.Add(channel_names[j], new List<double>());
    
}
dataStore[channel_names[j]].Add(measurement);

It will make it clearer that the measurment is always added to the list, regardless of the result of the ContainsKey method.

Upvotes: 2

Related Questions