Reputation: 6451
I have dictionary Dictionary<string, Point>
the Key is c1,c3,c2,t1,,t4,t2 I want to sort them to be c1,c2,c3,t1,t2,t3
I'm trying to sort it using
Input.OrderBy(key => key.Key );
but it doesn't work
any idea how to solve that
Upvotes: 61
Views: 154452
Reputation: 531
Load the unsorted object into a SortedDictionary
object like so:
var sortedCustomerData
= new SortedDictionary<string, string>(unsortedCustomerData);
Where unsortedCustomerData
is the same generic type (Dictionary string, string
or in your case string, point
). It will automatically sort the new object by key
According to msdn: SortedDictionary<TKey, TValue>(IDictionary<TKey, TValue>)
: Initializes a new instance of the SortedDictionary<TKey, TValue>
class that contains elements copied from the specified IDictionary<TKey, TValue>
and uses the default IComparer<T>
implementation for the key type.
Upvotes: 29
Reputation: 485
It depends what your needs are. If you need the keys out as a list a one time order by would work. I have made below test which you can run and see how to implement order by key.
[Fact]
public void SortDict()
{
// Arrange
var initial = new Dictionary<string, bool>()
{
{"c1", true },
{"c3", true },
{"c2", true },
{"t1", true },
{"t3", true },
{"t2", true },
};
var expected = new List<string>() { "c1", "c2", "c3", "t1", "t2", "t3" };
// Act
var actual = initial.OrderBy(k => k.Key).Select(k => k.Key)
.ToList();
// Assert
actual.ShouldBeEquivalentTo(expected);
}
If you instead need your keys to always be sorted I would use a SortedDictionary
. In below I'm creating a SortedDictionary
using its constructor with the old dictionary as parameter. You can run the test and verify the result.
[Fact]
public void SortDictUsingLinq()
{
// Arrange
var initial = new Dictionary<string, bool>()
{
{"c1", true },
{"c3", true },
{"c2", true },
{"t1", true },
{"t3", true },
{"t2", true },
};
var expected = new List<string>() { "c1", "c2", "c3", "t1", "t2", "t3" };
// Act
var sortedDict = new SortedDictionary<string, bool>(initial);
// Assert
sortedDict.Keys.ToList().ShouldBeEquivalentTo(expected);
}
SortedDictionary
has O(log n) insertion and retrieval times compared to Dictionary
which has O(1). Hence if it is only once or rarely you need elements sorted and you insert and remove often one time sort would be what you need.
Upvotes: -1
Reputation: 50712
Input.OrderBy
does not sort the dictionary, it creates a query that returns the items in a specific order.
Perhaps OrderedDictionary gives you what you want.
Or use the Generic SortedDictionary
Upvotes: 55
Reputation: 400
Since Input.OrderBy creates a query that returns the items in an ordered order, just assign it to the same dictionary.
objectDict = objectDict.OrderBy(obj => obj.Key).ToDictionary(obj => obj.Key, obj => obj.Value);
Upvotes: 32
Reputation: 47
The following code uses two more lists to sort a dictionary.
using System;
using System.Collections.Generic;
using System.Drawing;
namespace ConsoleApplication1 {
class Program {
static void Main(string[] args) {
Dictionary<string,Point> r=new Dictionary<string,Point>();
r.Add("c3",new Point(0,1));
r.Add("c1",new Point(1,2));
r.Add("t3",new Point(2,3));
r.Add("c4",new Point(3,4));
r.Add("c2",new Point(4,5));
r.Add("t1",new Point(5,6));
r.Add("t2",new Point(6,7));
// Create a list of keys
List<string> zlk=new List<string>(r.Keys);
// and then sort it.
zlk.Sort();
List<Point> zlv=new List<Point>();
// Readd with the order.
foreach(var item in zlk) {
zlv.Add(r[item]);
}
r.Clear();
for(int i=0;i<zlk.Count;i++) {
r[zlk[i]]=zlv[i];
}
// test output
foreach(var item in r.Keys) {
Console.WriteLine(item+" "+r[item].X+" "+r[item].Y);
}
Console.ReadKey(true);
}
}
}
The output of the code above is shown below.
c1 1 2
c2 4 5
c3 0 1
c4 3 4
t1 5 6
t2 6 7
t3 2 3
Upvotes: 3
Reputation: 4683
ok check this it should work
var r = new Dictionary<string, Point>();
r.Add("c3", new Point(0, 0));
r.Add("c1", new Point(0, 0));
r.Add("t3", new Point(0, 0));
r.Add("c4", new Point(0, 0));
r.Add("c2", new Point(0, 0));
r.Add("t1", new Point(0, 0));
r.Add("t2", new Point(0, 0));
var l = r.OrderBy(key => key.Key);
var dic = l.ToDictionary((keyItem) => keyItem.Key, (valueItem) => valueItem.Value);
foreach (var item in dic)
{
Console.WriteLine(item.Key);
}
Console.ReadLine();
Upvotes: -6
Reputation: 1905
Just a guess but it looks like you are assuming it is going to sort Input. The OrderBy method actually returns an ordered instance of an IOrderedEnumerable containing the same values. If you want to keep the return value you can do the below:
IOrderedEnumerable orderedInput
orderedInput = Input.OrderBy(key=>key.Key)
Most methods that would modify the collection follow this same pattern. It does this so that it is not changing the origional collection instance. This protects you from accidently changing the instance when you didn't intend to. If you do want to only use the sorted instance then you just set the variable to the return of the method as shown above.
Upvotes: 8
Reputation: 6451
I used
var l = Input.OrderBy(key => key.Key);
and I converted it to Dictionary
Upvotes: 0