I have code where I get an IDictionary and need to return an IImmutableDictionary. No problem, I just run the extension method ToImmutableDictionary().
Elsewhere, I get an IImmutableDictionary and need to return an IDictionary. Is there a preferred way of doing this?
Use imutable.ToDictionary(r=> r.Key, r=> r.Value) like:
Dictionary<int,int> dictionary = new Dictionary<int, int>();
IImmutableDictionary<int, int> imutable = dictionary.ToImmutableDictionary();
IDictionary<int, int> dictionary2 = imutable.ToDictionary(r=> r.Key, r=> r.Value);
Related
Help me with new theme "predicate"
I have a question to change this code for using predicate:
var d = dict.OrderBy(delegate(KeyValuePair<string,int> pair) { return pair.Value; });
But have no idea how it's working...
And where is the problem?
delegate(KeyValuePair<string, int> pair) { return pair.Value; } is the same as Func<KeyValuePair<string, int>, int>.
Thus you can easily replace your code by this:
var d = dict.OrderBy((KeyValuePair<string, int> pair) => pair.Value);
Or easier:
var d = dict.OrderBy(pair => pair.Value);
As the compiler can automatically infer the type of the instance within the delegate.
As an aside: a predicate is basically a method that expects an instance of your type (in your case KeyValuePair<string, int> and returns a bool, thus a Func<T, bool>.
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();
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
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.