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
Related
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());
}
}
Due to limitations on the system I am getting data from, I end up with duplicate Dictionaries in a orders list. The system looks at the amount of items and gives me one order for each item inside the order. Basically I end up with this:
List<Dictionary<string, string>> myOrders = new List<Dictionary<string, string>>();
Dictionary<string, string> dictionay = new Dictionary<string,string>();
dictionay.Add("OrderId", "00000082");
dictionay.Add("Order Status", "In Process");
myOrders.Add(dictionay);
Dictionary<string, string> dictionay1 = new Dictionary<string, string>();
dictionay1.Add("OrderId", "00000082");
dictionay1.Add("Order Status", "In Process");
myOrders.Add(dictionay1);
Dictionary<string, string> dictionay2 = new Dictionary<string, string>();
dictionay2.Add("OrderId", "00000083");
dictionay2.Add("Order Status", "In Process");
myOrders.Add(dictionay2);
Dictionary<string, string> dictionay3 = new Dictionary<string, string>();
dictionay3.Add("OrderId", "00000084");
dictionay3.Add("Order Status", "In Process");
myOrders.Add(dictionay3);
I am sure there is a simple way to do this but I am having a hard time to loop through the myOrders and compare the OrderId value in order to end up with distinct dictionaries within the list. Can anyone help?
First off - If each list item is a single entry, you might want to consider switching to List<Tuple<string,string>> or List<KeyValuePair<string,string>>.
That being said, you could get a unique list of OrderId values via something like:
var uniqueIds = new HashSet<string>(
myOrders
.SelectMany(o => o) // Extract all KeyValuePairs
.Where(kvp => kvp.Key == "OrderId")
.Select(kvp => kvp.Value));
I'd suggest first selecting out the distinct IDs:
IEnumerable<string> ids = myOrders.Select(order => order["OrderId"]).Distinct();
Then selecting the first dictionary corresponding to each id:
List<Dictionary<string, string>> distinctOrders =
ids.Select(id =>
myOrders.First(order => order["OrderId"] == id)).ToList();
I'd also suggest you shouldn't use Dictionaries for this purpose and should instead create an Order class with OrderId and OrderStatus as properties on that class.
Alternatively, if you don't mind adding a third-party dependency, you might consider morelinq, which has a DistinctBy method suitable for this. If you use that, you'd simply do:
List<Dictionary<string, string>> distinctOrders =
myOrders.DistinctBy(order => order["OrderId"]).ToList();
What is the most efficient way to cast a Dictionary<int, List<User>> to a Dictionary<int, IEnumerable<User>>?
The reason for this is that I have a method which builds a Dictionary<int, List<User>> but I would prefer not to return a mutable List to the calling code.
Would I have to project this dictionary into the new type?
You can do just like this:
var userDictionary = new Dictionary<int, List<User>>();
IDictionary<int, IEnumerable<User>> newDictionary = userDictionary.ToDictionary(p => p.Key, p => p.Value.AsEnumerable());
You can return an IEnumerable but under the hood it'll be a List. A developer may well cast it to a List and add or remove items
I think you're looking for Immutable Collections
Briefly, it's a nuget package that enable us to use/create truly immutable collections; meaning that any collections changes are not reflected back to what exposed them.
EDIT: Cast to IEnumerable does not grant immutability
Given Guilherme Oliveira answer one can do the following and add a new user to the users
var userDictionary = new Dictionary<int, List<User>>();
userDictionary.Add(1, new List<User>
{
new User{ Name= "Joseph"},
});
IDictionary<int, IEnumerable<User>> newDictionary = userDictionary.ToDictionary(p => p.Key, p => p.Value.AsEnumerable());
((List<User>) newDictionary.Values.First()).Add(new User {Name = "Maria"});
Console.WriteLine(newDictionary.Values.First().Count()); //now we have two users
You would need to project this to a new dictionary, e.g.
Dictionary<int, List<User>> myDictionary = ...;
Dictionary<int, IEnumerable<User>> resultingDictionary = myDictionary.ToDictionary(kvp => kvp.Key, kvp => (IEnumerable<User>)kvp.Value)
You are unable to perform a cast from Dictionary<int, List<User>> to Dictionary<int, IEnumerable<User>> because if you could, the following would be possible:
Dictionary<int, List<User>> myDictionary = ...;
// Still a reference to the original dictionary
Dictionary<int, IEnumerable<User>> castDictionary = myDictionary;
// If the line above was possible, what would this do? (A HashSet<T> is not a List<T>)
castDictionary.Add(5, new HashSet<User>());
You may also want to take a look at covariance and contravariance on interfaces to see where the limitations lie.
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]);
}
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();