.NET List<string> (call by reference?) with Dictionary objects - c#

I have the following code snippet:
Dictionary<int, List<string>> likeListDict = new Dictionary<int, List<string>>();
List<string> lists = new List<string>();
lists.Add("hello");
lists.Add("world");
likeListDict.Add(1, lists);
lists.Clear();
lists.Add("foobar");
likeListDict.Add(2, lists);
At the likeListDict.Add(1, lists) part, the "hello" and "world" get added in to key 1. But once I do the lists.Clear(), and add in the key 2 to likeListDict, both key 1 and 2 now have "foobar". How do I stop this (call by reference) and make it call by value?

There is no concept of "call by reference" or "call by value". List<T> is a reference type, so whatever you do to a given reference will be visible anywhere in the program where that reference exists.
What you want to do is create a new list instead of calling lists.Clear();
Dictionary<int, List<string>> likeListDict = new Dictionary<int, List<string>>();
List<string> lists = new List<string>();
lists.Add("hello");
lists.Add("world");
likeListDict.Add(1, lists);
lists = new List<string>();
lists.Add("foobar");
likeListDict.Add(2, lists);

Make a second list, don't try to reuse the first list. You're storing a reference to lists in the Dictionary, so adding it twice results in the same reference being in your dictionary twice, so changes to your list are reflected in both entries in the dictionary.
Ex:
public static void Main()
{
var likeListDict = new Dictionary<int, List<string>>();
var lists = new List<string> {"hello", "world"};
likeListDict.Add(1, lists);
var secondList = new List<string> {"foobar"};
likeListDict.Add(2, secondList);
}

Related

Compare 2 dictionaries and return missing values

How would I compare these 2 dictionaries and return only the values missing?
The GetFileListFromBlob() function gets all file names and I'd like to know what is missing from the db.
Or is there a better way to get the missing values from these objects? Should I use different key/ value?
Dictionary<int, string> databaseFileList = new Dictionary<int, string>;
Dictionary<int, string> blobFileList = new Dictionary<int, string>;
int counter = 0;
foreach (string f in GetFileListFromDB())
{
counter++;
databaseFileList.Add(counter, f );
}
counter = 0;
foreach (string f in GetFileListFromBlob())
{
counter++;
blobFileList.Add(counter, f);
}
// How to compare?
Thank you
A HashSet<T> might be what you want (instead of a Dictionary<K,V>) - take this example:
var reference = new HashSet<string> {"a", "b", "c", "d"};
var comparison = new HashSet<string> {"a", "d", "e"};
When you now call ExceptWith on the reference set ...
reference.ExceptWith(comparison);
... the reference set will contain the elements "b" and "c" that do not exist in the comparison set. Note however that the extra element "e" is not captured (swap the sets to get "e" as the missing element) and that the operation modifies the reference set in-place. If that isn't wished for, the Except LINQ operator might be worth investigating, as was already mentioned in another answer.
The way I see it, you don't need counters at first (you can add them later).
You can use System.Collections.Generic.List<> type to go on.
List<int, string> databaseFileList = new List<string>(GetFileListFromDB());
List<int, string> blobFileList = new List<string>(GetFileListFromBlob());
//some code
Now if you want to get all items in both lists you can simply use Concat(...) method to unify them and then use Distinct() method to remove duplicate items:
List<string> allItems = databaseFileList.Concat(blobFileList).Distinct();
Now use Except(...) method to compare collections:
var missingItems1 = allItems .Except(databaseFileList);
//or
var missingItems1 = allItems .Except(blobFileList);
//or
//some other code
private void CompareDictionary()
{
var databaseFileList = new Dictionary<int, string>();
var blobFileList = new Dictionary<int, string>();
databaseFileList.Add(300, "apple");
databaseFileList.Add(500, "windows");
databaseFileList.Add(100, "Bill");
blobFileList.Add(100, "Bill");
blobFileList.Add(200, "Steve");
var result = databaseFileList.Where(d2 => !blobFileList.Any(d1 => d1.Key == d2.Key)).ToList();
}

Create List with name from variable

Is it possible in C# to create a list and name it from a variable or similar?
Let's say I have a list with 10 rows in it:
a, b, c, d, e, f, g, h, i, j
Can I make 10 lists from this list, each having a name like one of the rows?
Something like
List<string> myList = new List<string>();
foreach (var line in myList)
{
List<string> line = new List<string>();
}
What I want is to make a few lists to store data in, but I won't know the names before the program runs so it needs to generate those dynamically.
Sounds like you want a Dictionary of List<string>s:
Dictionary<string, List<string>> dict = new Dictionary<string, List<string>>();
foreach (var line in myList)
{
dict.Add(line, new List<string>());
}
Now you can access each list based on the original string we used for the key:
List<string> aList = dict["a"];
You could try something like this:
var newList = new Dictionary<string, List<string>>();
foreach (var line in myList)
{
newList.Add(line, new List<string>());
}
This will give you the data structures in which to store your new data and will allow you to reference them based on the names in the first list.
It seems that you want a Dictionary<String, List<String>> like this:
var data = myList
.ToDictionary(line => line, line => new List<string>());
And so you can
check if "variable" exists
if (data.ContainsKey("z")) {...}
address "variable"
data["a"].Add("some value");
add "variable"
data.Add("z", new List<string>());

Dictionary if Key exist append if not add new element C#

I am having
Dictionary<String, List<String>> filters = new Dictionary<String, List<String>>();
which is having values like country = us. till now I am able to add it when key is not repeated. now when key country is repeated. it is showing that the key is already present.
what I want is How to add multiple values in the same key. I am not able to do it. Please suggest something.
for (int i = 0; i < msgProperty.Value.Count; i++)
{
FilterValue.Add(msgProperty.Value[i].filterValue.Value);
filterColumn = msgProperty.Value[i].filterColumnName.Value;
filters.Add(filterColumn, FilterValue);
}
what I want
country = US,UK
The different types of all your variables are a bit confusing, which won't help you writing the code. I'm assuming you have a Dictionary<string, List<string>> where the key is a "language" and the value is a list of countries for that language, or whatever. Reducing a problem to a minimal set that reproduces the issue is very helpful when asking for help.
Anyway assuming the above, it's as simple as this:
Try to get the dictionary["somelanguage"] key into existingValue.
If it doesn't exist, add it and store it in the same variable.
Add the List<string> to the dictionary under the "somelanguage" key.
The code will look like this:
private Dictionary<string, List<string>> dictionary;
void AddCountries(string languageKey, List<string> coutriesToAdd)
{
List<string> existingValue = null;
if (!dictionary.TryGetValue(languageKey, out existingValue))
{
// Create if not exists in dictionary
existingValue = dictionary[languageKey] = new List<string>()
}
existingValue.AddRange(coutriesToAdd);
}
You simply need to check whether the value exists in the dictionary, like this:
if (!filters.ContainsKey("country"))
filters["country"] = new List<string>();
filters["country"].AddRange("your value");
Assuming you are trying to add value for key country
List<string> existingValues;
if (filters.TryGetValue(country, out existingValues))
existingValues.Add(value);
else
filters.Add(country, new List<string> { value })
If your values is List<string>
List<string> existingValues;
if (filters.TryGetValue(country, out existingValues))
existingValues.AddRange(values);
else
filters.Add(country, new List<string> { values })
Make use of IDictionary interface.
IDictionary dict = new Dictionary<String, List<String>>();
if (!dict.ContainsKey("key"))
dict["key"] = new List<string>();
filters["key"].Add("value");

Adding new element within a list inside a dictionary

In a dictionary, I want to add a list of numbers for a given key.But I am unable to do it.
for(int i = 0 ; i < size ; i++){
string input = Console.ReadLine();
string[] inputList = input.Split(' ');
count[Convert.ToInt32(inputList[0])]++;
if(!map.ContainsKey(Convert.ToInt32(inputList[0]))){
map.Add(Convert.ToInt32(inputList[0]),new List<string>());
map_index.Add(Convert.ToInt32(inputList[0]),new List<int>());
}
}
The question is bit unclear. My understanding of your problem is as follows: You have a dictionary, a value of the dictionary is a list, and you have trouble adding an item to that list. Since you didn't explain your notation I'm using more general names, just to give you an idea what has to be done:
Dictionary<int, List<string>> myDict = new Dictionary<int, List<string>>();
if (myDict.ContainsKey(myKey))
{
myDict[myKey].Add(myVal);
}
else
{
myDict[myKey] = new List<string> { myVal };
}
If the key is not in the dictionary you create an entry together with the list and initialize the list with the new value. If the key is there you just access the list (by using myDict[myKey]) and add the new value to the list. Since the list is always created for a new key you don't have to worry that it's not initialized when adding a value for an existing key.
This could be one the efficient Solution and much easier than if-else.
Dictionary<int, List<string>> myDict = new Dictionary<int, List<string>>();
try
{
myDict[myKey].Add(myVal);
}
catch
{
myDict[myKey] = new List<string> { myVal };
}
There is a 'one-command-line' way to do this using AddOrUpdate from ConcurrentDictionary:
using System.Linq;
using System.Collections.Generic;
using System.Collections.Concurrent;
...
var dictionary = new ConcurrentDictionary<int, string[]>();
var itemToAdd = "item to add to key-list";
dictionary.AddOrUpdate(1, new[]{item1ToAdd}, (key, list) => list.Append(itemToAdd));
// If key 1 doesn't exist, creates it with a list containing itemToAdd as value
// If key 1 exists, adds item to already existent list (third parameter)

C# Dynamic List Name

I need to create few list in c# but want to name those list dynamically according to some condition.
For example
List<string> x1= new List<string>();
List<string> x2 = new List<string>();
The name "x1" and "x2" would come at runtime (probably from some file or something). Is there any way to achieve this ?
Create Dictionary<string, List<string>>:
var dict = new Dictionary<string, List<string>>();
dict["x1"] = new List<string>();
You can replace "x1" with variable.

Categories