質問

キーと値で構成される辞書を値で並べ替えなければならないことがよくあります。たとえば、単語とそれぞれの頻度のハッシュがあり、頻度順に並べ替えたいとします。

があります SortedList これは単一の値 (頻度など) に適しており、それを単語にマッピングし直す必要があります。

ソートされた辞書 値ではなくキーで注文します。に頼る人もいます カスタムクラス, 、しかしもっときれいな方法はありますか?

役に立ちましたか?

解決

使用:

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));

他のヒント

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 条項も同様です。

var ordered = dict.OrderBy(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 の方法に似ています。

Dictionary を値でソートし、それ自体に保存し直すことができます (これにより、foreach を実行すると、値が順番に出力されます)。

dict = dict.OrderBy(x => x.Value).ToDictionary(x => x.Key, x => x.Value);

確かに、それは正しくないかもしれませんが、機能します。

大まかに言うと、ディクショナリ全体を調べてそれぞれの値を確認する以外に選択肢はありません。

おそらくこれが役立つでしょう: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 を使用する必要があります。

ただし、あなたの場合、ソース構造は別のフィールドで並べ替えられているため、関係ありません。それでも、頻度で並べ替えて、関連するフィールド (頻度) で並べ替えられた新しいコレクションに入れる必要があります。したがって、このコレクションでは、周波数がキーであり、単語が値です。多くの単語が同じ頻度を持つ可能性があるため (それをキーとして使用することになるため)、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);
}
Dictionary<string, string> dic= new Dictionary<string, string>();
var ordered = dic.OrderBy(x => x.Value);
return ordered.ToDictionary(t => t.Key, t => t.Value);

または、楽しみのために、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));

値の並べ替え

これは、辞書内の値を並べ替える方法を示しています。Visual Studio でコンパイルして実行できるコンソール プログラムが表示されます。キーを辞書に追加し、値で並べ替えます。Dictionary インスタンスは、最初はいかなる方法でも並べ替えられていないことに注意してください。クエリ ステートメントで 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

並べ替え SortedDictionary バインドするリスト ListView VB.NET を使用して制御します。

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> クラス.

Bijection<K1, K2> 2 つの既存の辞書を使用してコレクションを初期化できるため、一方を並べ替えず、もう一方を並べ替えたい場合は、次のようなコードで全単射を作成できます。

var dict = new Bijection<Key, Value>(new Dictionary<Key,Value>(), 
                               new SortedDictionary<Value,Key>());

使用できます dict 通常の辞書と同様に (実装されています) IDictionary<K, V>)、そして電話します dict.Inverse でソートされた「逆」辞書を取得します。 Value.

Bijection<K1, K2> の一部です Loyc.Collections.dll, ただし、必要に応じて、単にコピーすることもできます ソースコード あなた自身のプロジェクトに。

注記:同じ値のキーが複数ある場合は使用できません Bijection, 、ただし、通常のサーバー間で手動で同期することもできます。 Dictionary<Key,Value> そして BMultiMap<Value,Key>.

次のような辞書があるとします。

   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);
        }

実際には、辞書ではsort()メソッドがあります。値によってソートに興味があるため、キーを提供するまで値を取得できません。

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;

それは保存している値の種類によっても異なります。
単一 (文字列、整数など) なのか、複数 (リスト、配列、ユーザー定義クラスなど) なのか、
単一の場合は、そのリストを作成してから並べ替えを適用できます。
ユーザー定義のクラスの場合、そのクラスはicomparableを実装する必要があります。
ClassName: IComparable<ClassName> そしてオーバーライド compareTo(ClassName c)LINQ よりも高速で、よりオブジェクト指向であるためです。

以下のコードを使用して、ディクショナリを値でソートし、ディクショナリ内の結果を取得できます。

Dictionary <<string, string>> ShareUserNewCopy = 
       ShareUserCopy.OrderBy(x => x.Value).ToDictionary(pair => pair.Key,
                                                        pair => pair.Value);                                          

辞書がある場合、以下の 1 つのライナーを使用して値に基づいて直接並べ替えることができます。

var x = (from c in dict orderby c.Value.Order ascending select c).ToDictionary(c => c.Key, c=>c.Value);
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top