Adding new element within a list inside a dictionary - c#

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)

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 a new list when I have new key while adding to Dictionary in a loop

I am trying to iterate a file reading data line by line. After reading I would like to store in Dictionary. keys are unique but values are having list of values for a key(may be 50 values per key). But while iterating keys comes randomly.How do I create a newlist for each key and store the value in the corresponding List when next time same key comes...how to store all those new keys and corresponding lists in dictionary.Please me on this..
Here is explanation of my code ..
Dictionary<String,List<PropertyCollection>> dict = new Dictionary<String,List<PropertyCollection>>();
List<String> list1 = new List<String>();
//Here I am iterating the each record and getting the type and id
for (i=1;i<datarr.length -1;i++){
String type = datarr[3].Trim();
String id = datarr[1].Trim();
//here I am checking the key in map adding
if(dict.ContainsKey(type)){
//I need help here if the key is not there create a new record with key as "type" and values as "id"s. All the values of same type should add in a list.If any new type comes in iteration it should add as new entry and having key and values are Ids in a list format.
I stuck here ..
}
}
I don't know how many "types " are there in that file .So I need to build the List dynamically.
Please help .
this is a pretty common scenario when working with a Dictionary whose value is a collection. You just need to make sure that the collection is initialized for that key before trying to add anything to it:
//using Dictionary<int, List<string>>
for(int i in ...)
{
if (!dict.ContainsKey(i))
dict[i] = new List<string>();
dict[i].Add("hello");
}
Now every new key coming in will get a fresh List<string>
Class to Build your data:
class DataBuilder
{
public Dictionary<string, List<string>> Data { get; } = new Dictionary<string, List<string>>();
public void Add(string key, string dataVal)
{
if (!Data.ContainsKey(key))
{
Data.Add(key, new BaseList<string>());
}
Data[key].Add(dataVal);
}
}
This is how you can use above class to build data while you are reading file(s):
static void Main(string[] args)
{
var builder = new DataBuilder();
builder.Add("Key1", "Test Data 1");
builder.Add("Key1", "Test Data 2");
builder.Add("Key2", "Test Data 3");
builder.Add("Key1", "Test Data 4");
}
Update as per your query: Change your code to this:
private void Process()
{
Dictionary<String, List<string>> dict = new Dictionary<String, List<string>>();
for (int i = 0; i < numOfRec - 1; i++)
{
//Code to Read record at index i into dataarr.
String type = datarr[3].Trim();
String id = datarr[1].Trim();
if (!dict.ContainsKey(type))
{
dict.Add(type, new BaseList<string>());
}
dict[type].Add(id);
}
}
}

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");

Check if an item exist in the dictionary and remove it from the dictionary in C# [duplicate]

This question already has answers here:
Remove Item in Dictionary based on Value
(6 answers)
Closed 9 years ago.
The question should be clear from the title itself. I need to check if an item exist in the dictionary and remove it from the dictionary in C#. The only catch is that i have to do this using only the value item and not the key.
The declaration is as below:
IDictionary<string, myCustomClassObject> clients = new IDictionary<string, myCustomClassObject>();
Now i fill in the dictionary by:
clients["key"] = myCustomClassObject1;
Now how can i find and remove this item myCustomClassObject1 from my Dictionary. I only want to use the value item and not the key
Is this doabale...if so please guide...
regards
Edit: Thank you all....got valuable comments...probably have some thinking to do ...thanks
It depends on how you need it to perform. If you can accept O(N) performance, you could just do something like:
foreach(var pair in clients) {
if(pair.Value == expected) {
clients.Remove(pair.Key);
break;
}
}
However, if you need faster you would need two dictionaries - one the reverse of the other (i.e. keyed by the instances). So when adding, you would do:
clientsByKey.Add(key, value);
clientsByValue.Add(value, key);
so you can do (to remove-by-value):
string key;
if(clientsByValue.TryGetValue(value, out key)) {
clientsByValue.Remove(value);
clientsByKey.Remove(key);
}
or similarly (to remove-by-key):
Foo value;
if(clientsByKey.TryGetValue(key, out value)) {
clientsByValue.Remove(value);
clientsByKey.Remove(key);
}
It's not very efficient to search a dictionary by it's values. However, you can use Linq to find all entries with a given value.
IEnumerable<KeyValuePair<string, myCustomClassObject>> pairs = clients
.Where(entry => entry.Value.Equals(myCustomClassObject1)).ToList();
foreach (KeyValuePair<string, myCustomClassObject> kv in pairs)
clients.Remove(kv.Key);
This should do it. It removes all clients having a given value.
while (clients.ContainsValue(myCustomClassObject1))
clients.Remove(clients.Where(x => x.Value == myCustomClassObject1).FirstOrDefault().Key);
Or create a new dictionary without the values you want removed
clients = clients.Where(x => x.Value != myCustomClassObject1).ToDictionary(k => k.Key, v => v.Value);
If the collection only contains one item with the value to be removed then you can use one of the other answers here, which will work just fine.
However, if your collection can have multiple items with the same value then you need to be careful.
You cannot modify a collection while iterating over it, so you will need to find the keys of all the items that you want to remove in one loop and put them in a list, and then iterate over that list in a separate loop to delete the items.
For example:
using System;
using System.Collections.Generic;
using System.Linq;
namespace Demo
{
class Program
{
void run()
{
var dict = new Dictionary<string, int>
{
{"Key1", 1},
{"Key2", 2},
{"Key3", 3},
{"Key4", 2},
{"Key5", 4}
};
int valueToRemove = 2;
var keysToRemove = (from element in dict
where element.Value == valueToRemove
select element.Key).ToList();
foreach (var key in keysToRemove)
dict.Remove(key);
foreach (var element in dict)
Console.WriteLine("Key = {0}, Value = {1}", element.Key, element.Value);
}
static void Main(string[] args)
{
new Program().run();
}
}
}
Use,
Following will remove only first matching value
client newClient = new client();
foreach(KeyValuePair<string, client> client in clients) {
if(client.value.equals(newClient)) {
clients.remove(client.key);
break;
}
}
Or if you want to remove all matching values,
foreach(var client in clients.Where(kvp => kvp.Value == newClient).ToList()) {
clients.Remove(client.Key);
}

c# How to sort a sorted list by its value column

i have a generic sorted list "results" with key = some filename and value = boolean.
I would like to sort the list by the boolean entry or value column. does anyone know how i can do this?
Thanks!
SortedList is optimized so that inertions occur in an ordered fashion, such that enumeration occurs in a sorted order at minimal cost. Anything else requires a re-sort. Thus:
SortedList<string,bool> l = new SortedList<string, bool>();
l.Add("a", true);
l.Add("b", false);
l.Add("c", true);
l.Add("d", false);
var orderByVal = l.OrderBy(kvp => kvp.Value);
but this enumeration will be significantly slower to calculate, and be performed up-front, requiring extra storage to do so.
Depending on your situation it might be cheaper to maintain 2 SortedList instances with the key/value reversed.
In .NET 2.0, you could add your items to a SortedList:
public static List<MyObject> SortedObjects(IEnumerable<MyObject> myList) {
SortedList<string, MyObject> sortedList = new SortedList<string, MyObject>();
foreach (MyObject object in myList) {
sortedList.Add(object.ValueIWantToSort, object);
}
return new List<MyObject>(sortedList.Values);
}
For descending all list items
list.OrderByDescending();
or
var list = list.OrderByDescending(x => x.Product.Name)
.ThenBy(x => x.Product.Price).ToList();
Normally that sorted by the first key on the list so if you swap the key and value on the add, then match that on the binding
that sample example i use and work fine
public static SortedList<string, string> GetCountries(string conn)
{
var dict = new SortedList<string, string>();
dict.Add("","Select One");
var sql = "SELECT [CountryID] ,[Descr] FROM [dbo].[Countries] Order By CountryID ";
using (var rd = GetDataReader(conn, sql))
{
while (rd.Read())
{
dict.Add(rd["Descr"].ToString(), rd["CountryID"].ToString());
}
}
return dict;
}
Dim List As SortedList(Of String, String) = VDB.CoreLib.DbUtils.GetCountries(connDB)
ddlBankCountry.DataSource = List
ddlBankCountry.DataTextField = "Key"
ddlBankCountry.DataValueField = "Value"
ddlBankCountry.DataBind()

Categories