How to sort a dictionary that contains dictionary? - c#

I have a dictionary that contains another dictionary as value
something like this
Dictionary<string, Dictionary<double,double>>
now I want to sort it by internal dictionary's value
how can I do that??

From the looks of your comment
sorry i am not expert on c#, would you suggest a way to store 3 values as one item?
I would suggest creating a class and sort on it like this
public class MyClass
{
public string StringProperty {get;set;}
public int FirstDoubleProperty {get;set;}
public int SecondDoubleProperty {get;set;}
}
Then create a collection like this
List<MyClass> MyClasscol = new List<MyClass>();
MyClass mc = new MyClass();
mc.StringProperty = "User1225072";
mc.FirstDoubleProperty = 5;
mc.SecondDoubleProperty = 6;
MyClasscol.Add(mc);
mc = new MyClass();
// and So on
then sort like this
var newsortedcollection = MyClasscol.OrderBy(x => x.FirstDoubleProperty);

Assuming you are now trying to figure out how to store and order a collection of objects with multiple properties, then you have a few options. Nikhil Agrawal's answer is a great solution but there are times when you may not need/want to create a custom class for this. For these situations (preferably when your code is private and not part of some API) then the alternatives below might be an option.
KeyValuePairs
Based on your requirements and your original post using dictionaries, it seems like instead of a dictionary of dictionaries (multi-tiered), you probably wanted a dictionary of keyvaluepairs (flat).
// using keyvaluepair
var keyValueDict = new Dictionary<string, KeyValuePair<double, double>>();
keyValueDict.Add("string", new KeyValuePair<double, double>(5.8, 7.4));
var sortedKeyValues = keyValueDict.OrderBy(x => x.Value.Key);
Tuples
An alternative to the not so pleasant KeyValuePair is the Tuple introduced in .NET 4. The tuple is a generic class which allows you to store typed property values without creating your own custom class. It is worth noting that there are tuple implementations for up to 8 properties.
// using tuple
var tupleList = new List<Tuple<string, double, double>>();
tupleList.Add(new Tuple<string, double, double>("string", 5.8, 7.4));
var sortedTuples = tupleList.OrderBy(x => x.Item2);
There are some good SO questions about Tuples if you are interested:
Is Using .NET 4.0 Tuples in my C# Code a Poor Design Decision?
Are EventArg classes needed now that we have generics

Related

How can I map multipul lists to one key on C#?

I need to map one string (sentence) in to two lists (similar sentences indexes and the different word in each one).
By using "Dictionary" I have to use 2 dictionaries to save each list.
Is there other way to save a string as a key to int[] and string[]?
this is how it lookes now:
Dictionary<string, int[]> similarSentences = new Dictionary<string, int[]>();
Dictionary<string, string[]> changes = new Dictionary<string, string[]>();
I want someting like this:
Dictionary<string, int[],string[]> similarSentencesAndChanges = new Dictionary<string, int[],string[]>();
Thank you!
You could use tuples:
Dictionary<string,(int[] Similar, string[] Changes)> similarSentencesAndChanges = new Dictionary<string,(int[] Similar, string[] Changes)>();
and then you can access it like this:
var someKey = "somekey";
(int[] similar, string[] changes) = similarSentencesAndChanges[someKey];
However, depending on what you plan to do, randomly using tuples is a bad practice and you'd be wise in creating a class that contains both collections.
class SentenceData
{
public int[] Similar {get;}
public string[] Changes {get;}
}
Then, make your dictionary of type Dictionary<string, SentenceData>.
This has the added benefit of allowing the reuse of the object in other parts of your code. Furthermore, adding properties to the object at a latter stage won't involve potentially rewriting large parts of your code.
Assuming you are ok to use tuples, you could create an extension method for the generic Dictionary<TKey, TValue> type, which returns a dictionary with tuple values...
public static Dictionary<TKey, (TValue, TValue2)> Combine<TKey, TValue, TValue2>(this Dictionary<TKey, TValue> a, Dictionary<TKey, TValue2> b)
{
return a.Keys.Union(b.Keys).ToDictionary(x => x, x => (
a.ContainsKey(x) ? a[x] : default,
b.ContainsKey(x) ? b[x] : default
));
}
Example usage...
var similarSentencesAndChanges = similarSentences.Combine(changes);

List to be accessible only with Enumeration

What would be the best way to make a System.Collections.Generic.List that should only be accessed by an enum? To help describe what I'm looking for, this how I'm doing it right now:
enum MyEnum
{
First,
Second,
Count
}
class MyClass
{
List<SomeClass> myList = new List<SomeClass>((int)MyEnum.Count);
MyClass()
{
myList[(int)MyEnum.First] = new SomeClass(1);
myList[(int)MyEnum.Second] = new SomeClass(2);
}
}
I feel like I'm missing something. Is there a better way of doing this? I'm sorry if the answer is obvious, I found it very difficult to search for something that sounded so generic.
As some background, I would be using this list to access different textures in my code, e.g. the enum would have texture names and each texture would be placed in and later accessed from the List using that texture name.
Would it be possible to use Dictionary instead of List?
var myDict = new Dictionary<MyEnum, SomeClass>();
...
myDict[MyEnum.First] = new SomeClass(1);
myDict[MyEnum.Second] = new SomeClass(2);
Or, as #JimHurley suggested (see http://msdn.microsoft.com/en-us/library/bb531208.aspx) just
var myDict = new Dictionary<MyEnum, SomeClass>()
{
{ MyEnum.First, new SomeClass(1)},
{ MyEnum.Second, new SomeClass(2)}
};
If you want to add a new element to List<T> you have to use it's Add method.Indexer can be used only to modify existing items. I think in this case using a Dictionary<MyEnum, SomeClass> would be more appropriate.

BinarySearch in two dimensional list

I have dimensional list:
List<List<string>> index_en_bg = new List<List<string>>();
index_en_bg.Add(new List<string>() { word1, translation1 });
index_en_bg.Add(new List<string>() { word2, translation2 });
index_en_bg.Add(new List<string>() { word3, translation3 });
I would do binary search by the first column (words), something like this:
int row = index_en_bg.BinarySearch(searchingstr);
but it works only for a one-dimensional list. How would I extend it to work for two-dimensional lists in my case? I don't want to use Dictionary class.
In this case you need to provide your own customer IComparer-implementing comparator
public class Comparer: IComparer<IList<string>>
{
public int Compare(IList<string> x, IList<string> y)
{
// base the comparison result on the first element in the respective lists
// eg basically
return x[0].CompareTo(y[0]);
}
And you'll call it like this, offering a List where only the field you're searching is filled in.
int row = index_en_bg.BinarySearch(new List<string>() {searchingstr},new Comparer());
Well as far as I understand you should use Dictionary<K,V> instead, this way:
// 1 creating the dictionary
var dic = new Dictionary<string, string>();
dic["word1"] = "translation1";
dic["word2"] = "translation2";
dic["word3"] = "translation3";
// 2 finding a translation
var trans = dic["word1"];
And Dictionary<K,V> is really performant.
But if you insist on using BinarySearch you can implement IComparer<List<string>> and pass it to the function.
As you always search using the first item of the list you could use dictionary too.
var d = Dictionary<string, List<string>>();
as answered previously it's preforms much better than List.

creating a generic collection of key and values in C# 4.0

I need something like Dictionary where dynamic can be anything from string to objects.
But when i use objects, i need to know the type of the object and then access the appropriate properties of those objects.
Is there a way WITHOUT using Reflection.
* EDITED **
I tried to use this :
CloneObject<T, TU>(IDictionary<T, TU> sourceObject)
But if i use this, how can i access T's public fields without using reflection
You can use Hashtable for this purpose
Here is the Examples
http://www.dotnetperls.com/hashtable
You can also use Dictionary which is more efficient than Hashtable
See Examples Here:
http://www.dotnetperls.com/dictionary-keys
I'm confused a little bit. You trying to store any types of objects in your dictionary but access to them without reflection.
If so you can use dynamic types:
Dictionary dict = new Dictionary();
dict["string"] = "some string";
dict["int"] = 25;
dict["my_class"] = new MyClass {SomeProperty = 12};
And then you can access all this values without any casts:
string s1 = dict["string"].Substring(0, 4); // s1 equals to "some"
int propertyValue = dict["my_class"].SomeProperty; // propertyValue equals to 12
where MyClass is:
class MyClass
{
public int SomeProperty {get;set;}
}
Without using reflection, this task cannot be completed. All I have done is create clones of objects separately and then used them.

Immutable set in .NET

Does the .NET BCL have an immutable Set type? I'm programming in a functional dialect of C# and would like to do something like
new Set.UnionWith(A).UnionWith(B).UnionWith(C)
But the best I can find is HashSet.UnionWith, which would require the following sequence of calls:
HashSet composite = new HashSet();
composite.UnionWith(A);
composite.UnionWith(B);
composite.UnionWith(C);
This use is highly referentially opaque, making it hard to optimize and understand. Is there a better way to do this without writing a custom functional set type?
The new ImmutableCollections have:
ImmutableStack<T>
ImmutableQueue<T>
ImmutableList<T>
ImmutableHashSet<T>
ImmutableSortedSet<T>
ImmutableDictionary<K, V>
ImmutableSortedDictionary<K, V>
More info here
About the union this test passes:
[Test]
public void UnionTest()
{
var a = ImmutableHashSet.Create("A");
var b = ImmutableHashSet.Create("B");
var c = ImmutableHashSet.Create("C");
var d = a.Union(b).Union(c);
Assert.IsTrue(ImmutableHashSet.Create("A", "B", "C").SetEquals(d));
}
Update
This answer was written some time ago, and since then a set of immutable collections have been introduced in the System.Collections.Immutable namespace.
Original answer
You can roll out your own method for this:
public static class HashSetExtensions {
public static HashSet<T> Union<T>(this HashSet<T> self, HashSet<T> other) {
var set = new HashSet<T>(self); // don't change the original set
set.UnionWith(other);
return set;
}
}
Use it like this:
var composite = A.Union(B).Union(C);
You can also use LINQ's Union, but to get a set, you'll need to pass the result to the HashSet constructor:
var composite = new HashSet<string>(A.Union(B).Union(C));
But, HashSet itself is mutable. You could try to use F#'s immutable set.
Also, as mentioned in the comments by ErikE, using Concat yields the same result and probably performs better:
var composite = new HashSet<string>(A.Concat(B).Concat(C));
There is a ReadOnlyCollection, but it's not a hash table. LINQ adds the Union method as an extension.

Categories

Resources