キーとハッシュと値で構成される辞書を、値でソートする必要があることがよくあります。例えば、単語とそれぞれの頻度のハッシュを持っていて、頻度順に並べたい。
一つの値(例えば頻度)に適したSortedList
があり、それを単語にマッピングして戻したいのです。
SortedDictionaryは、値ではなく、キーで注文します。カスタムクラス](http://www.codeproject.com/KB/recipes/lookupcollection.aspx)に頼る人もいますが、もっときれいな方法はないでしょうか?
使用する:
using System.Linq.Enumerable;
...
List<KeyValuePair<string, string>> myList = aDictionary.ToList();
myList.Sort(
delegate(KeyValuePair<string, string> pair1,
KeyValuePair<string, string> pair2)
{
return pair1.Value.CompareTo(pair2.Value);
}
);
.NET 2.0以上をターゲットにしているので、これを簡略化してラムダ構文にすることができます(これと同等ですが、より短いです)。Visual Studio 2008 (またはそれ以上)のコンパイラを使用している場合のみ、この構文を使用することができます。
var myList = aDictionary.ToList();
myList.Sort((pair1,pair2) => pair1.Value.CompareTo(pair2.Value));
LINQを使用します。
Dictionary<string, int> myDict = new Dictionary<string, int>();
myDict.Add("one", 1);
myDict.Add("four", 4);
myDict.Add("two", 2);
myDict.Add("three", 3);
var sortedDict = from entry in myDict orderby entry.Value ascending select entry;
これにより、上位10、20、10%などを選択できるという大きな柔軟性も得られます。 または、「type-ahead」にワード周波数インデックスを使用している場合は、「StartsWith」句を含めることもできます。
高いところでは、ディクショナリー全体を歩いて、各バリューを見る以外の選択肢はない。
もしかしたら、これが役に立つかもしれません: http://bytes.com/forum/thread563638.html ジョン・ティムニーからのコピー・ペーストです:
Dictionary<string, string> s = new Dictionary<string, string>();
s.Add("1", "a Item");
s.Add("2", "c Item");
s.Add("3", "b Item");
List<KeyValuePair<string, string>> myList = new List<KeyValuePair<string, string>> (s);
myList.Sort(
delegate(KeyValuePair<string, string> firstPair、
KeyValuePair<string, string> nextPair) です。
{
return firstPair.Value.CompareTo(nextPair.Value);
}
);
とにかく辞書を並べ替えることはできません。 彼らは実際に注文されていません。 ディクショナリの保証は、キーと値のコレクションが反復可能であり、値がインデックスまたはキーで取得できることですが、特定の順序の保証はありません。 したがって、名前値のペアをリストに入れる必要があります。
辞書のエントリをソートしません。 .NETの辞書クラスはハッシュテーブルとして実装されています-このデータ構造は定義によってソートできません。
コレクションを(キーで)反復できる必要がある場合は、バイナリ検索ツリーとして実装されているSortedDictionaryを使用する必要があります。
ただし、別のフィールドでソートされるため、ソース構造は無関係です。 頻度で並べ替え、関連するフィールド(頻度)で並べ替えた新しいコレクションに入れる必要があります。 したがって、このコレクションでは、周波数はキーであり、単語は値です。 多くの単語は同じ頻度を持つことができるため(キーとして使用するため)、辞書もSortedDictionaryも使用できません(一意のキーが必要です)。 これにより、SortedListが残ります。
メイン/ファースト辞書の元のアイテムへのリンクを維持することを主張する理由がわかりません。
コレクション内のオブジェクトがより複雑な構造になっている場合。 (より多くのフィールド。) また、いくつかの異なるフィールドをキーとして使用して効率的にアクセス/ソートできるようにする必要がありました。おそらく、Oをサポートするメインストレージで構成されるカスタムデータ構造が必要になります。(1。) 挿入と削除。 (LinkedList。) およびいくつかのインデックス構造-辞書/ SortedDictionaries / SortedLists。 これらのインデックスは、複雑なクラスのフィールドの1つをキーとして使用し、LinkedListNode< YourClass>へのポインター/参照を使用します。 LinkedListで値として。
インデックスをメインコレクション(LinkedList)と同期させるには、挿入と削除を調整する必要があり、削除はかなり費用がかかると思います。 これは、データベースインデックスの動作に似ています。ルックアップには最適ですが、多くの挿入と削除を実行する必要がある場合に負担になります。
上記のすべては、ルックアップの重い処理を行う場合にのみ正当化されます。 周波数で並べ替えられたときにのみ出力する必要がある場合は、(匿名)タプルのリストを作成できます。
var dict = new SortedDictionary<string, int>();
// ToDo: populate dict
var output = dict.OrderBy(e => e.Value).Select(e => new {frequency = e.Value, word = e.Key}).ToList();
foreach (var entry in output)
{
Console.WriteLine("frequency:{0}, word: {1}",entry.frequency,entry.word);
}
値をソートします。
これは、辞書で値をソートする方法を示しています。 Visual Studioでコンパイルして実行できるコンソールプログラムが表示されます。 辞書にキーを追加し、値で並べ替えます。 辞書インスタンスは、最初はまったくソートされないことに注意してください。 クエリステートメントでは、LINQ orderbyキーワードを使用します。
OrderBy句。 辞書[C#]をソートするプログラム。
using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
static void Main()
{
// Example dictionary.
var dictionary = new Dictionary<string, int>(5);
dictionary.Add("cat", 1);
dictionary.Add("dog", 0);
dictionary.Add("mouse", 5);
dictionary.Add("eel", 3);
dictionary.Add("programmer", 2);
// Order by values.
// ... Use LINQ to specify sorting by value.
var items = from pair in dictionary
orderby pair.Value ascending
select pair;
// Display results.
foreach (KeyValuePair<string, int> pair in items)
{
Console.WriteLine("{0}: {1}", pair.Key, pair.Value);
}
// Reverse sort.
// ... Can be looped over in the same way as above.
items = from pair in dictionary
orderby pair.Value descending
select pair;
}
}
出力。
dog: 0
cat: 1
programmer: 2
eel: 3
mouse: 5
VB.NETを使用して「ListView」コントロールにバインドする「SortedDictionary」リストの並べ替え:
Dim MyDictionary As SortedDictionary(Of String, MyDictionaryEntry)
MyDictionaryListView.ItemsSource = MyDictionary.Values.OrderByDescending(Function(entry) entry.MyValue)
Public Class MyDictionaryEntry ' Need Property for GridViewColumn DisplayMemberBinding
Public Property MyString As String
Public Property MyValue As Integer
End Class
XAML:
<ListView Name="MyDictionaryListView">
<ListView.View>
<GridView>
<GridViewColumn DisplayMemberBinding="{Binding Path=MyString}" Header="MyStringColumnName"></GridViewColumn>
<GridViewColumn DisplayMemberBinding="{Binding Path=MyValue}" Header="MyValueColumnName"></GridViewColumn>
</GridView>
</ListView.View>
</ListView>
ソートされた辞書を取得する最も簡単な方法は、組み込みの「SortedDictionary」クラスを使用することです。
//Sorts sections according to the key value stored on "sections" unsorted dictionary, which is passed as a constructor argument
System.Collections.Generic.SortedDictionary<int, string> sortedSections = null;
if (sections != null)
{
sortedSections = new SortedDictionary<int, string>(sections);
}
sortedSections
には、 sections
のソートバージョンが含まれます。
「一時」リストを値でソートすることだけが必要な場合は、他の回答は適切です。 ただし、 Key
でソートされた辞書を、 Value
でソートされた別の辞書と_自動同期する_にしたい場合は、[Bijection< K1、K2>
class](http:// ecsharp.net / doc / classLoyc_1_1Collections_1_1Bijection.html)。
Bijection< K1、K2>
を使用すると、2つの既存の辞書でコレクションを初期化できます。そのため、そのうちの1つをソート解除し、もう1つをソートする場合は、コードなどのバイジェクションを作成できます。
var dict = new Bijection<Key, Value>(new Dictionary<Key,Value>(),
new SortedDictionary<Value,Key>());
通常の辞書と同様に「dict」を使用して(「IDictionary< K、V>」を実装します)、次に「dict.Inverse」を呼び出して、「Value」でソートされた「inverse」辞書を取得できます。
Bijection< K1、K2>
はLoyc.Collections.dllの一部ですが、必要に応じて、[ソースコード](https://github.com/qwertie/Loyc/blob/master/Core/Loyc.Collections/Other.
注:同じ値の複数のキーがある場合、「Bijection」は使用できませんが、通常の「Dictionary< Key、Value>」と[BMultiMap< Value、Key>
]を手動で同期できます。 '](http://loyc.net/doc/code/classLoyc_1_1.
辞書があるとします。
Dictionary<int, int> dict = new Dictionary<int, int>();
dict.Add(21,1041);
dict.Add(213, 1021);
dict.Add(45, 1081);
dict.Add(54, 1091);
dict.Add(3425, 1061);
sict.Add(768, 1011);
1) 一時辞書を使用して、値を
として保存できます。
Dictionary<int, int> dctTemp = new Dictionary<int, int>();
foreach (KeyValuePair<int, int> pair in dict.OrderBy(key => key.Value))
{
dctTemp .Add(pair.Key, pair.Value);
}
実際にはC#では、辞書にはsort()メソッドがあります。 値でソートすることにもっと興味があるので。 キーを提供するまで値を取得できません。 要するに、あなたはそれらを通して反復する必要があります。 LINQの注文者を使用します。
var items = new Dictionary<string, int>();
items.Add("cat", 0);
items.Add("dog", 20);
items.Add("bear", 100);
items.Add("lion", 50);
// Call OrderBy method here on each item and provide them the ids.
foreach (var item in items.OrderBy(k => k.Key))
{
Console.WriteLine(item);// items are in sorted order
}
1つのトリックを実行できます。
var sortedDictByOrder = items.OrderBy(v => v.Value);
または。
var sortedKeys = from pair in dictName
orderby pair.Value ascending
select pair;
また、どのような値を保存しているかにも依存します。
単一(文字列、intなど)または複数(リスト、配列、ユーザー定義クラスなど)ですか。
シングルの場合は、リストを作成してソートを適用できます。
ユーザー定義クラスの場合。
次に、そのクラスはIComparableを実装する必要があります。
ClassName:IComparable< ClassName>
および compareTo(ClassName c)
をオーバーライドします。
それらはLINQよりも速く、オブジェクト指向であるため。