How to get the value of an inner Dictionary? - c#

Here is my dictionary.
var dic = new Dictionary<string, Dictionary<string, int>>();
I need to get the value of the int in the inner dictionary.
foreach (var country in dic)
{
output.AppendFormat("{0} (total population: {1})", country.Key, HERE);
}
Any help?

If you want a population sum ("total popuplation"), you can use:
var sum = country.Value.Values.Sum();
output.AppendFormat("{0} (total population: {1})", country.Key, sum);
This uses LINQ, so you are required to have
using System.Linq;
in your source file.

Try to run this sample in degugger:
var dic = new Dictionary<string, Dictionary<string, int>>();
var cities = new Dictionary<string, int>();
cities.Add("Kiev", 6000000);
cities.Add("Lviv", 4000000);
dic.Add("Ukraine", cities);
var totalPopulationByCountry = dic.ToDictionary(x => x.Key, y => y.Value.Values);
var sumPopulationByCountry = dic.ToDictionary(x => x.Key, y => y.Value.Values.Sum());
should be what you need

Related

list of dictionaries order by value C#

How can I order by value in descending order following the dictionary list
List<Dictionary<int, int>> myList = new List<Dictionary<int, int>>();
Dictionary<int, int> obj = new Dictionary<int, int>();
obj.Add(1, 2);
myList.Add(obj);
myList.Add(obj);
Dictionary<int, int> obj2 = new Dictionary<int, int>();
obj2.Add(2, 4);
myList.Add(obj2);
Dictionary<int, int> obj3 = new Dictionary<int, int>();
obj3.Add(3, 3);
myList.Add(obj3);
myList.Add(obj3);
myList.Add(obj3);
expected output will be
[0][2,4],
[1][3,3],
[2][3,3],
[3][3,3],
[4][1,2],
[5][1,2]
you can do something like this
var orderedValues = myList
.SelectMany(x => x)
.OrderByDescending(x => x.Value)
.ToList();
and output the data
for (int i = 0; i < orderedValues.Count(); i++)
{
Console.WriteLine($"[{i}][{orderedValues[i].Key},{orderedValues[i].Value}]");
}

Parsing nested dictionary with LINQ

I have a JSON object that I am Deserializing using Newtonsoft.Json into a Dictionary<string, Dictionary<string, string>>
I want to parse it into a Dictionary<string, Dictionary<double, int>> using LINQ however I am struggling to do this with the nested part.
For un-nested Dictionaries I am just using .ToDictionary(k => double.Parse(k.Key), k => int.Parse(k.Value))
Thanks
var input = new Dictionary<string, Dictionary<string, string>>();
input.Add("test1", new Dictionary<string, string>());
input["test1"].Add("1.2", "3");
var output = input.ToDictionary(
x => x.Key,
x => x.Value.ToDictionary(
y => double.Parse(y.Key),
y => int.Parse(y.Value)
)
);
should do the trick.

Combining multiple dictionary where key matches

I get a
Dictionary<DateTime,double>()
from different part of an application. This can return a number of dictionaries which is why I store them in a list:
var masterlist = new List<Dictionary<DateTime, double>>();
I would like to combine the dictionaries now where the DateTime key is equal and turn the result into an array object[,] so that each row looks like this:
DateTime, double_d1, double_d2, ... double_dn
where d1, d2, ..., dn is mock code for the dictionaries in the list.
how can I do this please?
You can try this :
Dictionary<DateTime, double[]> preResult = masterlist.SelectMany(s => s).GroupBy(k => k.Key)
.ToDictionary(k => k.Key, v => v.Select(s => s.Value).ToArray());
var result = preResult.Select(s =>
{
var res = new List<object>();
res.Add(s.Key);
res.AddRange(s.Value.Cast<object>());
return res.ToArray();
}).ToArray();
Here is similar solution to #Ksv3n, where the result is the Dictionary of DateTime as key and List of doubles as value:
Dictionary<DateTime, List<double>> masterDic = masterlist
.SelectMany(dic => dic)
.GroupBy(dic => dic.Key)
.ToDictionary(dic => dic.Key, values => values.Select(v => v.Value).ToList());
You can use Dictionary<DateTime, List<double>>. You loop thru the list of dictionary you have and add entries in to this dictionary.
var masterlist = new List<Dictionary<DateTime, double>>();
Dictionary<DateTime, List<double>> dtDoubles = new Dictionary<DateTime, List<double>>();
foreach (var item in masterlist)
{
foreach (var kvPair in item)
{
if (!dtDoubles.ContainsKey(kvPair.Key))
{
dtDoubles.Add(kvPair.Key, new List<double> {kvPair.Value});
}
else
{
dtDoubles[kvPair.Key].Add(kvPair.Value);
}
}
}
How about this:
Dictionary<DateTime, List<double>> result =
masterlist.Select(x => x.AsEnumerable())
.Aggregate((a, b) => a.Concat(b))
.GroupBy(x => x.Key)
.ToDictionary(k => k.Key, v => v.Select(x => x.Value).ToList());

How to join two dictionaries?

I have two dictionaries. If the values in dict2 are same then we have to add the values for the matching keys from dict1 and generate a result in the result dictionary as given below.
**dict1** **dict2**
Id value Id value
24379 348 24379 270451
24368 348 24368 270451
24377 90 24377 270450
24366 90 24366 270450
24369 10 24369 270450
24300 25
Result:
24379 696
24368 696
24377 190
24366 190
24369 190
I have the following logic and would like to optimize this solution:
Dictionary<int, int> result = new Dictionary<int, int>();
foreach (int itemKey in dict1.keys)
{
result.add (itemKey, dict1.Where(a => dict2.ContainsKey(a.key)
&& dict2.ContiansKey(itemKey)
&& dict2[a.key] == dict2[itemKey])
.Sum(a => a.value);
}
You can do it in two steps:
Prepare a dictionary for looking up the value by dict2's value
Walk through dict1, and insert values from the look-up dictionary
Here is how you can do it:
var lookup = dict1
.Where(p => dict2.ContainsKey(p.Key))
.GroupBy(p => dict2[p.Key])
.ToDictionary(g => g.Key, g => g.Sum(p => p.Value));
var res = dict1.Keys
.Where(k => dict2.ContainsKey(k))
.ToDictionary(k => k, k => lookup[dict2[k]]);
Demo.
public static void DicAddTest()
{
Dictionary<int, int> dic1 = new Dictionary<int, int>() { {24379,348}, { 24368, 348 }, { 24377, 90 }, { 24366, 90 } };
Dictionary<int, int> dic2 = new Dictionary<int, int>() { { 24379, 270451 }, { 24368, 270451 }, { 24377, 270450 }, { 24366, 270450 } };
Dictionary<int, int> dicResult = DicAdd(dic1, dic2);
foreach (KeyValuePair<int, int> kvp in dicResult)
Debug.WriteLine("{0} {1}", kvp.Key, kvp.Value);
Debug.WriteLine("");
}
public static Dictionary<int, int> DicAdd(Dictionary<int, int> dic1, Dictionary<int, int> dic2)
{
Dictionary<int, int> dicResult = new Dictionary<int, int>(dic1);
foreach (int k in dic1.Keys.Where(x => dic2.Keys.Contains(x)))
dicResult[k] = dicResult[k] + dicResult[k];
return dicResult;
}
question is not clear
public static Dictionary<int, int> DicAdd2(Dictionary<int, int> dic1, Dictionary<int, int> dic2)
{
Dictionary<int, int> dicResult = new Dictionary<int, int>();
foreach (KeyValuePair<int, int> kvp in dic1.Where(x => dic2.Keys.Contains(x.Key)))
dicResult.Add(kvp.Key, 2 * kvp.Value);
return dicResult;
}
Perhaps it's easier to do like this, if you are not sure that dict1 and dict2 will have the same keys:
var result = new Dictionary<int, int>();
foreach(var kvp in dict1)
{
int value;
if(dict2.TryGetValue(kvp.Key, out value))
{
result[kvp.Key] = kvp.Value * 2;
}
}
This will only add values present in both dictionaries. If your Dictionary is very big, you could perhaps use a Parallel For, or consider use Hashtable instead.

How to check for duplicates in an array and then do something with their values?

I have an array for example("1:2","5:90","7:12",1:70,"29:60") Wherein ID and Qty are separated by a ':' (colon), what I want to do is when there's a duplicate of IDs the program will add the qty and return the new set of arrays so in the example it will become ("1:72","5:90","7:12","29:60").
Ex.2 ("1:2","5:90","7:12","1:70","29:60","1:5") becomes ("1:77","5:90","7:12","29:60").
I want to solve it without using linq.
var foo = array.Select(s => s.Split(':'))
.GroupBy(x => x[0])
.Select(g =>
String.Format(
"{0}:{1}",
g.Key,
g.Sum(x => Int32.Parse(x[1]))
)
)
.ToArray();
Note, it's not necessary to parse the "keys," only the values.
Without LINQ:
var dictionary = new Dictionary<string, int>();
foreach (var group in array) {
var fields = group.Split(':');
if (!dictionary.ContainsKey(fields[0])) {
dictionary.Add(fields[0], 0);
}
dictionary[fields[0]] += Int32.Parse(fields[1]);
}
string[] foo = new string[dictionary.Count];
int index = 0;
foreach (var kvp in dictionary) {
foo[index++] = String.Format("{0}:{1}", kvp.Key, kvp.Value);
}
You have to do this manually. Loop through each list, check the ID for each element. Put it in a Dictionary<int, int>, Dictionary<id, qt>. If the dictionary contains the id, add it to the value.
Loop, add, check using Dictionary class.
If you want it without LINQ...
var totalQuantities = new Dictionary<int, int>();
foreach(var raw in sourceArr) {
var splitted = raw.Split(':');
int id = int.Parse(splitted[0]);
int qty = int.Parse(splitted[1]);
if(!totalQuantities.ContainsKey(id)) {
totalQuantities[id] = 0;
}
totalQuantities[id] += qty;
}
var result = new string[totalQuantities.Count];
int i=0;
foreach(var kvp in totalQuantities) {
result[i] = string.Format("{0}:{1}", kvp.Key, kvp.Value);
i++;
}
(
from raw in arr
let splitted = raw.Split(':')
let id = int.Parse(splitted[0])
let qty = int.Parse(splitted[1])
let data = new { id, qty }
group data by data.id into grp
let totalQty = grp.Sum(val => val.qty)
let newStr = string.Format("{0}:{1}", grp.Key, totalQty
select newStr
)
.ToArray()
Note that the code may contain accidental errors, as it was written in notepad.
var input=new string[]{"1:2","5:90","7:12","1:70","29:60","1:5"};
var result=input
.Select(s=>s.Split(':'))
.Select(x=>x.Select(s=>int.Parse(s)).ToArray())
.GroupBy(x=>x[0])
.Select(g=>g.Key+":"+g.Sum(x=>x[1]));
I was too lazy to specify the culture everywhere. You probably want to do that before putting it into production, or it will fail for cultures with unusual integer representations.
var totals=new Dictionary<int,int>
foreach(string s in input)
{
string[] parts=s.Split(':');
int id=int.Parse(parts[0]);
int quantity=int.Parse(parts[0]);
int totalQuantity;
if(!totals.TryGetValue(id,out totalQuantity))
totalQuantity=0;//Yes I know this is redundant
totalQuanity+=quantity;
totals[id]=totalQuantity;
}
var result=new List<string>();
foreach(var pair in totals)
{
result.Add(pair.Key+":"+pair.Value);
}
try this:
List<string> items = new List<string>(new string[] { "1:2", "5:90", "7:12", "1:70", "29:60" });
Dictionary<string, int> dictionary = new Dictionary<string, int>();
foreach (string item in items)
{
string[] data = item.Split(':');
string key = data[0];
if (!dictionary.ContainsKey(data[0]))
{
int value = dictionary[data[0]];
dictionary[key] += int.Parse(data[1]);
}
}
//Used dictionary values here

Categories

Resources