Parsing nested dictionary with LINQ - c#

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.

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

Get Except of multiple nested dictionaries using LINQ expression

I want to get different of n numbers of dictionaries using a lambda expression:
Dictionary<string, string> d1 = new Dictionary<string, string>();
d1.Add("Joe", "2, Barfield Way");
d1.Add("Mike", "17, Apollo Avenue");
d1.Add("Jane", "69, Lance Drive");
Dictionary<string, string> d2 = new Dictionary<string, string>();
d2.Add("Joe", "2, Barfield Way");
d2.Add("Jane", "69, Lance Drive");
// var diff = d1.Except(d2);
Let say I want to get the difference of two above dictionaries var diff = d1.Except(d2);
Now I want to get the same out using lambda expression for N numbers of dictionaries.
For an instant, I have merged two dictionaries into one. I want to get a difference of two dictionaries using lambda expression or any other LINQ expression.
Dictionary<string, Dictionary<string, string>> d = new Dictionary<string, Dictionary<string, string>>();
d.Add("Test", d1);
d.Add("Test2", d2);
I have tried the expression below but could not get any results.
d.Select(c => c.Value.Except(c.Value))
You need some Linq methods:
var result = d.SelectMany(d => d.Value).GroupBy(c => c.Key)
.Where(c => c.Count() == 1).ToDictionary(t => t.Key, t => t.Select(c => c.Value)
.FirstOrDefault()).ToList();
Convert it to a collection of KeyValuePair<> enumerables and follow the same logic using .Aggregate()
var result = d.Select(x => x.Value.AsEnumerable()).Aggregate((x, y) => x.Except(y));
You can store the Dictionaries in a List<Dictionary<string, string>>.
Then query this collection and group by the keys , filter by count of key to get the unique ones only, then build a new Dictionary :
var d1 = new Dictionary<string, string>
{
{ "Joe", "2, Barfield Way" },
{ "Mike", "17, Apollo Avenue" },
{ "Jane", "69, Lance Drive" }
};
var d2 = new Dictionary<string, string>
{
{ "Joe", "2, Barfield Way" },
{ "foo", "bar" },
{ "Jane", "69, Lance Drive" }
};
var d3 = new Dictionary<string, string>
{
{ "hello", "world" },
{ "foo", "bar" }
};
var dicts = new List<Dictionary<string, string>>
{
d1,
d2,
d3
};
var distinct = dicts.SelectMany(d => d) // Flatten the collection of dictionaries
.GroupBy(d => d.Key) // Group the sequence by key
.Where(d => d.Count() == 1) // Filter the result for unique keys only
.ToDictionary(k => k.Key, v => v.Select(x => x.Value)
.First()); // Materialize the sequence in a Dictionary<string, string>
foreach (var key in distinct.Keys)
{
Console.WriteLine($"{key} -> {distinct[key]}");
}
Output is
Mike -> 17, Apollo Avenue
hello -> world
This way you will get the same result:
Dictionary<string, string> d1 = new Dictionary<string, string>();
d1.Add("Joe", "2, Barfield Way");
d1.Add("Mike", "17, Apollo Avenue");
d1.Add("Jane", "69, Lance Drive");
Dictionary<string, string> d2 = new Dictionary<string, string>();
d2.Add("Joe", "2, Barfield Way");
d2.Add("Jane", "69, Lance Drive");
var diff = d1.Except(d2);
Dictionary<string, Dictionary<string, string>> d = new Dictionary<string, Dictionary<string, string>>();
d.Add("Test", d1);
d.Add("Test2", d2);
var diff1 = d.SelectMany(x => x.Value).GroupBy(x => new { x.Key, x.Value }).Where(x => x.Count() == 1).SelectMany(x => x.AsEnumerable());

How to convert List<Tuple<int, int>> to Dictionary<int, List<int>>?

I have duplicate keys with different values and I want to convert it to a dictionary with 1 key and its values.
The next example will explain best what I mean:
var tup = new List<Tuple<int, int>>();
tup.Add(new Tuple<int, int>(1, 1));
tup.Add(new Tuple<int, int>(1, 2));
var dic = new Dictionary<int, List<int>>();
What is an elegant way to convert the tup to dic?
I managed to do this with foreach but would like to write it in LINQ.
foreach (var item in tup)
{
if (dic.ContainsKey(item.Item1))
{
dic[item.Item1].Add(item.Item2);
}
else
{
dic.Add(item.Item1, new List<int> { item.Item2 });
}
}
var list = tup.GroupBy(x => x.Item1)
.ToDictionary(
x => x.Key,
x => x.Select(y => y.Item2).ToList());
First, we group by GroupBy item 1. This should be obvious enough.
Then, we call ToDictionary and pass in a keySelector and an elementSelector. They select the key and value respectively, given an IGrouping<int, Tuple<int, int>>.
For reference, this particular overload of ToDictionary is used.
Alternatively, as Iridium has said in the comments, this works as well:
var list = tup.GroupBy(x => x.Item1, x => x.Item2)
.ToDictionary(x => x.Key, x => x.ToList());
This overload of GroupBy allows you to select 2 things!
You first need to group by the first tuple element in order to find all elements that have the same key in the dictionary. And then just collect the second tuple elements and make a list out of it:
tup.GroupBy(t => t.Item1)
.ToDictionary(g => g.Key, g => g.Select(t => t.Item2).ToList());
You can use GroupBy to resolve this problem, like:
var tup = new List<Tuple<int, int>>();
tup.Add(new Tuple<int, int>(1, 1));
tup.Add(new Tuple<int, int>(1, 2));
var dic = tup
.GroupBy(x => x.Item1)
.ToDictionary(x => x.Key, tuples => tuples.Select(x => x.Item2).ToList());
BTW, in some cases you can use NameValueCollection, but this is not save your target type, for example
var nvc = tup.Aggregate(new NameValueCollection(),
(seed, current) =>
{
seed.Add(current.Item1.ToString(), current.Item2.ToString());
return seed;
});
foreach (var item in nvc)
{
Console.WriteLine($"Key = {item} Value = {nvc[item.ToString()]}");
}

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 get the value of an inner Dictionary?

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

Categories

Resources