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.
Related
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);
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);
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
I am working on C# converting a dictionary to query :
public class myClass
{
public int my_id;
public Dictionary<string, Dictionary<string, string[]>> myDict;
}
Dictionary<string, myClass> dataDict;
var queryDict = (from happen in dataDict
group happen by happen.Value.my_id into g select g)
.ToDictionary(g => g.Key, g => g.ToDictionary(x => x.Key, x => x.Value));
I need to iterate every element of queryDict.
Before doing the query, for the same dataDict's key, there may be multiple myClass that have the same event_id.
After query, for the same happen.Value.my_id, how the dataDict' s original keys are organized ? They are a list pointed by the one event_id ?
Any help would be appreciated !
Effectively, your dataDict is an array of KeyValuePair (1-dimensonal array). And your query adds another dimension, so it becomes a Dictionary of Dictionaries. But adding another dimension is just a grouping of older elements by a new key.
It's better to illustrate it like this:
Basically group by gives you an IGrouping<TKey, TElement> which is an IEnumerable<TElement> (IGrouping Interface), so having this query:
from happen in dataDict group happen by happen.Value.my_id into g select g
means, you group by happen.Value.my_id, so the TKey will be my_id and the TElement would be a KeyValuePair<string, MyClass>> which is the items of your dictionary. Since the IGrouping<int, KeyValuePait<stirng, MyClass>> which is the result of above query is actually an IEnumerable<keyValuePair<string, MyClass>>, so for every key you actually have an IEnumerable<KeyValuePair<string, MyClass>>. As you can see here, you have the elements of you dictionary as they were.
Second part of the query is just converting the IEnumerable<IGrouping<int, Dictionary<string, MyClass>>> to a Dictionary<int, Dictionary<string, MyClass>>> so it's not big deal.