多くの場合、辞書(キーと値で構成される)を値で並べ替える必要があります。たとえば、頻度別に並べ替えたい単語とそれぞれの頻度のハッシュがあります。
SortedList
単語にマップし直したい単一の値(たとえば頻度)に適したものがあります。
SortedDictionaryは、値ではなくキーで並べ替えられます。カスタムクラスに頼る人もいますが、よりクリーンな方法はありますか?
多くの場合、辞書(キーと値で構成される)を値で並べ替える必要があります。たとえば、頻度別に並べ替えたい単語とそれぞれの頻度のハッシュがあります。
SortedList
単語にマップし直したい単一の値(たとえば頻度)に適したものがあります。
SortedDictionaryは、値ではなくキーで並べ替えられます。カスタムクラスに頼る人もいますが、よりクリーンな方法はありますか?
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
使用する:
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以降を対象としているため、これをラムダ構文に単純化できます。これは同等ですが、より短くなります。.NET 2.0を対象としている場合、この構文は、Visual Studio 2008(またはそれ以降)のコンパイラーを使用している場合にのみ使用できます。
var myList = aDictionary.ToList();
myList.Sort((pair1,pair2) => pair1.Value.CompareTo(pair2.Value));
あなたが使用することができます:
var ordered = dict.OrderBy(x => x.Value).ToDictionary(x => x.Key, x => x.Value);
周りを見回して、いくつかのC#3.0機能を使用して、これを行うことができます。
foreach (KeyValuePair<string,int> item in keywordCounts.OrderBy(key=> key.Value))
{
// do something with item.Key and item.Value
}
これは私が見た中で最もクリーンな方法であり、ハッシュを処理するRubyの方法に似ています。
ディクショナリを値で並べ替えて、それ自体に保存し直すことができます (そのため、foreach すると値が順番に表示されます)。
dict = dict.OrderBy(x => x.Value).ToDictionary(x => x.Key, x => x.Value);
確かに、それは正しくないかもしれませんが、うまくいきます。ハイラムの法則は、これが機能し続ける可能性が非常に高いことを意味します。
大まかに言えば、辞書全体を調べて各値を確認する以外に選択肢はありません。
たぶんこれは役に立ちます:http: //bytes.com/forum/thread563638.html John Timneyからのコピー/貼り付け:
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を使用する必要があります。
ただし、あなたの場合、ソース構造は別のフィールドでソートされているため、関係ありません。それでも頻度で並べ替えて、関連するフィールド(頻度)で並べ替えた新しいコレクションに入れる必要があります。したがって、このコレクションでは、頻度はキーであり、単語は値です。多くの単語が同じ頻度を持つ可能性があるため(そしてそれをキーとして使用する予定です)、DictionaryもSortedDictionaryも使用できません(一意のキーが必要です)。これにより、SortedListが残ります。
メイン/最初の辞書の元の項目へのリンクを維持することを主張する理由がわかりません。
コレクション内のオブジェクトがより複雑な構造(より多くのフィールド)を持ち、いくつかの異なるフィールドをキーとして使用してそれらに効率的にアクセス/ソートできる必要がある場合-おそらく、メインストレージで構成されるカスタムデータ構造が必要になります。 O(1)の挿入と削除(LinkedList)およびいくつかのインデックス構造(Dictionaries / SortedDictionaries / SortedLists)をサポートします。これらのインデックスは、複合クラスのフィールドの1つをキーとして使用し、LinkedList内のLinkedListNodeへのポインター/参照を値として使用します。
インデックスをメインコレクション(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);
}
または、楽しみのために、LINQ 拡張機能を使用することもできます。
var dictionary = new Dictionary<string, int> { { "c", 3 }, { "a", 1 }, { "b", 2 } };
dictionary.OrderBy(x => x.Value)
.ForEach(x => Console.WriteLine("{0}={1}", x.Key,x.Value));
VB.NET を使用してコントロールSortedDictionary
にバインドするリストを並べ替える:ListView
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>
ソートされた Dictionary を取得する最も簡単な方法は、組み込み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
次の辞書があるとします。
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)使用できますtemporary dictionary to store values as
:
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);
}
ディクショナリは定義上、ハッシュ可能な方法で値とキーのみを含む順序付けられていない連想構造です。言い換えれば、辞書を注文するための事前に見える方法はありません。
参考までに、Python 言語のこの記事をお読みください。
Python データ構造をリンク する
次のコードを使用して、辞書を値で並べ替え、結果を辞書で取得できます。
Dictionary <<string, string>> ShareUserNewCopy =
ShareUserCopy.OrderBy(x => x.Value).ToDictionary(pair => pair.Key,
pair => pair.Value);
辞書がある場合は、以下のライナーを使用して値で直接並べ替えることができます。
var x = (from c in dict orderby c.Value.Order ascending select c).ToDictionary(c => c.Key, c=>c.Value);