Dictionary Manipulation Using LINQ in C# - c#

I'm having a Dictionary like
Dictionary<String, List<String>> MyDict = new Dictionary<string, List<string>>
{
{"One",new List<String>{"A","B","C"}},
{"Two",new List<String>{"A","C","D"}}
};
I need to get a List<String> from this dictionary, The List should contain Distinct items from the values of the above dictionary.
So the resulting List will contain {"A","B","C","D"}.
Now I'm using for loop and Union operation. Like
List<String> MyList = new List<string>();
for (int i = 0; i < MyDict.Count; i++)
{
MyList = MyList.Union(MyDict[MyDict.Keys.ToList()[i]]).Distinct().ToList();
}
Can any one suggest me a way to do this in LINQ or LAMBDA Expression.

var items=MyDict.Values.SelectMany(x=>x).Distinct().ToList();
Or an alternative:
var items = (from pair in MyDict
from s in pair.Value
select s).Distinct().ToList();

Related

How to convert Dictionary to List with mixing of values and keys?

I have some dictionary. Let it be:
var dictionary = new Dictionary< string, List<MyClass>>();
I need to convert it to list of object that contains property from key and value.
I did it with foreach loop in the next way:
var list = new List<dynamic>();
foreach (var key in dictionary.Keys)
{
var values = dictionary[key];
foreach (var obj in values)
{
list.Add(new
{
obj.Property0,
obj.Property1,
obj.Property2,
...
key
}
);
}
}
It works, but looks rudely as for me. Is it possible to do it more gracefully with LINQ?
You can do that with a SelectMany.
var list = dictionary.SelectMany(
kvp => kvp.Value,
(kvp,obj) => new {obj.Property0, obj.Property1, obj.Property2, kvp.Key})
.ToList();
Or in query snytax
var list = (from kvp in dictionary
from obj in kvp.Value
select new {obj.Property0, obj.Property1, obj.Property2, kvp.Key})
.ToList();
Note this results in a list of an anonymous class. If you really want dynamic you'll need to do a Cast<dynamic>() before the ToList(). Also if you want the last property of the anonymous class to be key instead of Key you'll need to do key = kvp.Key.

Linq Distinct() or GroupBy() method is not working in below scenario

In below code I have multiple instance of the dictionary bundled into a list. Now I want to select only distinct values from the list. To do this I tried using distinct and group by but that never helped me. Can any one please help me in selecting only distinct using linq?
IList<Dictionary<string, string>> lst = new List<Dictionary<string, string>>();
Dictionary<string, string> d = new Dictionary<string, string>();
Dictionary<string, string> d1 = new Dictionary<string, string>();
Dictionary<string, string> d3 = new Dictionary<string, string>();
d.Add("12345", "xyz");
d1.Add("12345", "xyz");
d3.Add("123456", "xyz-abc");
lst.Add(d);
lst.Add(d1);
lst.Add(d3);
var result = lst.Distinct(); //test => test.Values.ToString().Trim()); //.Select(grp => grp.First());
If you would like get the distict values over all dictionaries then you need to compare the acctual elements in each dictionary to select all elements you could use SelectMany like this:
Key/Value pairs:
var result = lst.SelectMany(x=>x).Distinct();
Values:
var result = lst.SelectMany(x=>x.Values).Distinct();
Keys:
var result = lst.SelectMany(x=>x.Keys).Distinct();
You have to select the values from the list first, then apply Distinct():
var values = lst.SelectMany(dict => dict); // or lst.SelectMany(dict => dict.Values), I don't know what kind of values you mean
var distinctValues = values.Distinct();
The class Dictionary<TKey, TValue> does not override the Equals(object) and GetHashCode() methods. For that reason you get reference-equality semantics when you use .Distinct() (or GroupBy etc.).
d and d1 refer two different instances (two different objects). These two dictionaries happen to have the same keys with the same corresponding values, but that does not make them the same instance. Therefore, d != d1 (as references).
You might want to do instead:
var result = lst.Distinct(new YourDictEqualsComparer());
where YourDictEqualsComparer is the following class:
// naive string-string dictionary equality comparer
class YourDictEqualsComparer : EqualityComparer<Dictionary<string, string>>
{
public override bool Equals(Dictionary<string, string> x, Dictionary<string, string> y)
{
if (x == null || y == null)
return Default.Equals(x, y);
if (!x.Comparer.Equals(y.Comparer))
return false;
var setOfPairs = new HashSet<KeyValuePair<string, string>>(x);
return setOfPairs.SetEquals(y);
}
public override int GetHashCode(Dictionary<string, string> obj)
{
if (obj == null)
return 0;
int seed = obj.Comparer.GetHashCode();
return obj.Aggregate(seed, (hash, pair) => hash ^ pair.GetHashCode());
}
}

How to find out Union of Dictionary Values in C#?

I need to find out Union of dictionary Values. I have created the dictionary below.
Dictionary<int, List<string>> dict = new Dictionary<int, List<string>>();
List<string> ls1 = new List<string>();
ls1.Add("1");
ls1.Add("2");
ls1.Add("3");
ls1.Add("4");
List<string> ls2 = new List<string>();
ls2.Add("1");
ls2.Add("5");
dict.Add(1, ls1);
dict.Add(2, ls2);
So in this case Output would be {"1","2","3","4","5"}
As a Dictionary<TKey, TValue> implements IEnumerable<KeyValuePair<TKey, TValue>> you may use Linq.
The following Linq will get what you are after:
dict.SelectMany(kvp => kvp.Value).Distinct()
The SelectMany will select all of the elements of the lists, the Distinct() ensures duplicate elements are only returned once.
As stated in the comment, you require a List<string> of the result, so the code may be extended to:
var result = dict.SelectMany(kvp => kvp.Value).Distinct().ToList();
You just need to flatten the values and eliminate the duplicates using Distinct:
dict.SelectMany(x => x.Value).Distinct();
To get union of your values, you could use LINQ Union:
dict.Values.Union(dict.Values);

Order a dictionary without using Linq OrderBy

I'm trying to order a C# Dictionary<int, int> by its value without using LINQ's OrderBy as it's not supported on iPhones.
I can't seem to figure it out, so your help would be much appreciated!
There are many possible ways of doing this. All of the following assume myDictionary is the original dictionary to be sorted.
① Create a list and then sort the list
var myList = myDictionary.ToList();
myList.Sort((a, b) => a.Value.CompareTo(b.Value));
② Create an array and then sort the array
var myArray = myDictionary.ToArray();
Array.Sort(myArray, (a, b) => a.Value.CompareTo(b.Value));
③ Create a new SortedDictionary that has keys and values swapped
This solution is appropriate only if you know that every value occurs only once.
var mySortedDict = new SortedDictionary<int, int>();
foreach (var kvp in myDictionary)
mySortedDict[kvp.Value] = kvp.Key;
④ Create a new SortedDictionary and use lists for values
This solution is appropriate only if values can occur more than once.
var mySortedDict = new SortedDictionary<int, List<int>>();
foreach (var kvp in myDictionary)
{
if (!mySortedDict.ContainsKey(kvp.Value))
mySortedDict[kvp.Value] = new List<int>();
mySortedDict[kvp.Value].Add(kvp.Key);
}
We can generate a List of KeyValuePair and then sort it using Sort,
Dictionary<int, int> myList = new Dictionary<int, int>();
List<KeyValuePair<int, int>> mySortedList = myList.ToList();
mySortedList.Sort(( firstValue, nextValue) =>
{
return firstValue.Value.CompareTo(nextValue.Value);
}
);
Dictionary<int, int> mySortedDict = mySortedList.ToDictionary(keyItem => keyItem.Key, keyItem => keyItem.Value);
I think Sort will be supported on iPhones

Use ToDictionary to create a dictionary

I have two string lists which have same size.
I want to create a dictionary, the key is from listA, the value is from listB.
What is the fast way?
I used the code:
List<string> ListA;
List<string> ListB;
Dictionary<string,string> dict = new Dictionary<string,string>();
for(int i=0;i<ListA.Count;i++)
{
dict[key] = listA[i];
dict[value]= listB[i];
}
I don't like this way, can I use ToDictionary method?
Starting with .NET 4.0, you can do it using LINQ's Zip method, like this:
var res = ListA.Zip(ListB, (a,b) => new {a, b})
.ToDictionary(p=>p.a, p=>p.b);
[Zip] method merges each element of the first sequence with an element that has the same index in the second sequence.
You could create an anonymous type with the index which you can use to get the B at this index.
Dictionary<string, string> dict = ListA
.Select((a, i) => new { A = a, Index = i })
.ToDictionary(x => x.A, x => ListB.ElementAtOrDefault(x.Index));
Note that the value would be null in case ListB is smaller than ListA.
I would not bother (if it is possible) as your version is readable, easy to debug and quicker than any other LINQ solutions (especially if you are working with big list).
I wouldn't change your version.
The following piece of code is more readable than LINQ stuff in your case, IMHO.
var ListA = new List<string>();
var ListB = new List<string>();
var dict = new Dictionary<string, string>();
for (int i = 0; i < ListA.Count; i++)
{
dict.Add(ListA[i], ListB[i]);
}

Categories

Resources