How to join two dictionaries? - c#

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.

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

Transform Dictionary<string, int> to Dictionary<int, List<string>>

Q How can I most efficiently convert a Dictionary<string, int> to a Dictionary<int, List<string>>?
Example
var input = new Dictionary<string, int>() { {"A", 1}, {"B", 1}, {"C", 2} ...
Dictionary<int, List<string>> result = Transform(input)
Assert.IsTrue(result, { {1, {"A", "B"}}, {2, {"C"}} ... });
Group the dictionary by values and map the group keys to list of keys:
input.GroupBy(x => x.Value).ToDictionary(x => x.Key, x => x.Select(_ => _.Key).ToList())
How about this?
var result =
dict.ToLookup(x => x.Value, x => x.Key)
.ToDictionary(y => y.Key, y => y.ToList());
Although I don't see why you couldn't just use the result from dict.ToLookup() without changing it to a dictionary, for example:
var dict = new Dictionary<string, int>
{
{"One", 1},
{"Two", 2},
{"1", 1},
{"TWO", 2},
{"ii", 2}
};
var test = dict.ToLookup(x => x.Value, x => x.Key);
Console.WriteLine(string.Join(", ", test[2])); // Prints: Two, TWO, ii
You can use Linq to achieve.
private static Dictionary<int, List<string>> Transform(Dictionary<string, int> input)
{
var result = new Dictionary<int, List<string>>();
foreach (var value in input.Select(x => x.Value).Distinct())
{
var lst = input.Where(x => x.Value == value).Select(x => x.Key).ToList();
result.Add(value, lst);
}
return result;
}

How to Multiply and sum nested dictionary in C#?

I have a Dictionary in C# with this structure :
Dictionary<int, Dictionary<string, double>> dictionary = new Dictionary<int, Dictionary<string, double>>
{
{
0, new Dictionary<string, double>
{
{ "eat",0.15 },
{ "food", 0.16 }
}
},
{
1, new Dictionary<string, double>
{
{ "eat",0.32 },
{ "food", 0.2 }
}
},
};
I want to sum and multiply eat in other dictionary,
0.15 * 0.32 + 0.16 * 0.2
what should i do to code this in c# with foreach?
thankyou
Here is a LINQ solution:
Dictionary<int, Dictionary<string, double>> dict = new Dictionary<int, Dictionary<string, double>>() {
{0,new Dictionary<string, double> { { "eat",0.15 }, { "food", 0.16 } } },
{1,new Dictionary<string, double> { { "eat",0.32 }, { "food", 0.2 } } }
};
double eat = dict.Values.Select(x => x["eat"]).Aggregate((x, y) => x * y);
double food = dict.Values.Select(x => x["food"]).Aggregate((x, y) => x * y);
double result = eat + food;
EDIT
Here is a more compact and universal solution:
var result = dict.SelectMany(x => x.Value)
.GroupBy(x => x.Key, y => y.Value, (Key, Value) => new { Value })
.Sum(x => x.Value.Aggregate((a, b) => a * b));
result = 0.08
DEMO HERE
You can do this
var dict = new Dictionary<int, Dictionary<string, double>>() {
{0, new Dictionary<string, double>() {{"eat", 0.15}, {"food", 0.16}}},
{1, new Dictionary<string, double>() {{"eat", 0.32}, {"food", 0.2}}}};
var total = dict.Values.SelectMany(x => x) // Flatten
.GroupBy(x => x.Key) // Group by key
.Sum(x => x.Select(y => y.Value) // sum list of sub values
.Aggregate((y, z) => y * z)); // multiply
Console.WriteLine(total);
Output
0.08
Full Demo here
You can solve this problem using foreach loop and some linq at the end as following:
Dictionary<int, Dictionary<string, double>> data = new Dictionary<int, Dictionary<string, double>>()
{
{
0,new Dictionary<string, double>(){{ "eat" , 0.15 },{ "food" , 0.16} }
},
{
1,new Dictionary<string, double>(){{ "eat" , 0.32 },{ "food" , 0.2 } }
}
};
Dictionary<string, double> finalResultDic = new Dictionary<string, double>();
foreach (var entry in data)
{
foreach (var subEntry in entry.Value)
{
if (finalResultDic.ContainsKey(subEntry.Key))
{
finalResultDic[subEntry.Key] *= subEntry.Value;
}
else
{
finalResultDic.Add(subEntry.Key, subEntry.Value);
}
}
}
var finalResult = finalResultDic.Sum(dic => dic.Value);
Try following :
Dictionary<int, Dictionary<string, double>> dict = new Dictionary<int,Dictionary<string,double>>() {
{0, new Dictionary<string,double>() {{"eat" , 0.15}, {"food" , 0.16}}},
{1, new Dictionary<string,double>(){{"eat", 0.32},{"food", 0.2}}}
};
double total = dict.Select(x => x.Value.Select(y => x.Key * y.Value).Sum()).Sum();

Simplest way to add all content of Dictionary<T1, T2> to another Dictionary<T1, T2> (equal types for key & value)?

Is there a simpler way to copy/add all content of source dictionary to destination Dictionary<T1, T2> object than using one of the two options in the sample below?
Dictionary<string, int> source = new Dictionary<string, int>(),
destination = new Dictionary<string, int>();
source.Add("Developers", 1);
source.Add("just", 2);
source.Add("wanna have", 3);
source.Add("FUN!", 4);
// Option 1 (feels like a hack):
//
source.All(delegate(KeyValuePair<string, int> p)
{
destination.Add(p.Key, p.Value);
return true;
});
// Option 2:
//
foreach (string k in source.Keys)
{
destination.Add(k, source[k]);
}
What I was looking for is something like .ForEach().
Yes, you can use the constructor:
Dictionary<string, int> destination = new Dictionary<string, int>(source);
If destination is already filled and you don't want to lose them as commented i'd use this:
foreach (var kv in source)
if (!destination.ContainsKey(kv.Key))
destination.Add(kv.Key, kv.Value);
You can use Concat:
Dictionary<string, int> dict1 = new Dictionary<string, int>();
dict1.Add("first", 1);
Dictionary<string, int> dict2 = new Dictionary<string, int>();
dict2.Add("second", 2);
dict2 = dict2.Concat(dict1).ToDictionary(k => k.Key, v => v.Value);
This of course doesn't really 'add' it to the dictionary, but replaces it by a new one. You can use Union to get rid of duplicates.
static void Main()
{
Dictionary<string, int> source = new Dictionary<string, int>();
Dictionary<string, int> destination = new Dictionary<string, int>();
destination.Add("Apple", 1);
destination.Add("Banana", 2);
foreach (var item in destination)
{
source.Add(item.Key, item.Value);
}
foreach (var item in destination)
{
Console.WriteLine("Key is {0} and value is {1}", item.Key, item.Value);
}
}

A library like Python's collections.Counter library for C# -> Getting the difference of values between two dictionary objects in C#

This is how I would create a Dictionary in C#.
Dictionary<string, int> d = new Dictionary<string, int>()
{
{"cheese", 2},
{"cakes", 1},
{"milk", 0},
{"humans", -1} // This one's for laughs
};
In Python if you have a dictionary like so:
from collections import Counter
my_first_dict = {
"cheese": 1,
"cakes": 2,
"milk": 3,
}
my_second_dict = {
"cheese": 0,
"cakes": 1,
"milk": 4,
}
print Counter(my_first_dict) - Counter(my_second_dict)
>>> Counter({'cheese': 1, 'cakes': 1})
As you can see, Counter is very useful when comparing dictionary objects.
Is there a library in C#, that will allow me to do something similar to this, or do I have to code it from scratch?
You can join the two dictionaries together and then create a new one based on the given operation with only a few lines of code:
Dictionary<string, int> d1 = new Dictionary<string, int>();
Dictionary<string, int> d2 = new Dictionary<string, int>();
var difference = d1.Join(d2, pair => pair.Key, pair => pair.Key, (a, b) => new
{
Key = a.Key,
Value = a.Value - b.Value,
})
.Where(pair => pair.Value > 0)
.ToDictionary(pair => pair.Key, pair => pair.Value);
There is no system class that you've shown that wraps a dictionary an provides a - operator for them, but you can make your own if you want easily enough:
public class Counter<T> : IEnumerable<KeyValuePair<T, int>>
{
private IEnumerable<KeyValuePair<T, int>> sequence;
public Counter(IEnumerable<KeyValuePair<T, int>> sequence)
{
this.sequence = sequence;
}
public static Counter<T> operator -(Counter<T> first, Counter<T> second)
{
return new Counter<T>(first.Join(second
, pair => pair.Key, pair => pair.Key, (a, b) =>
new KeyValuePair<T, int>(a.Key, a.Value - b.Value))
.Where(pair => pair.Value > 0));
}
public IEnumerator<KeyValuePair<T, int>> GetEnumerator()
{
return sequence.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
There's no built-in functionality like this, but you can use a bit of Linq:
Dictionary<string, int> first = new Dictionary<string, int>()
{
{"cheese", 1},
{"cakes", 2},
{"milk", 3},
};
Dictionary<string, int> second = new Dictionary<string, int>()
{
{"cheese", 0},
{"cakes", 1},
{"milk", 4},
};
var results =
(from x in first
join y in second on x.Key equals y.Key
where x.Value - y.Value > 0
select new { x.Key, Value = x.Value - y.Value })
.ToDictionary(p => p.Key, p => p.Value);
// returns a dictionary like { { "cheese", 1 }, { "cakes", 1 } }

Categories

Resources