cipher = new Dictionary<char,int>;
cipher.Add( 'a', 324 );
cipher.Add( 'b', 553 );
cipher.Add( 'c', 915 );
2番目の要素を取得する方法は?たとえば、次のようなものが欲しい:
KeyValuePair pair = cipher[1]
ペアに( 'b', 553 )
が含まれる場合
リストを使用した協同組合の提案に基づいて、物事は機能しています:
List<KeyValuePair<char, int>> cipher = new List<KeyValuePair<char, int>>();
cipher.Add( new KeyValuePair<char, int>( 'a', 324 ) );
cipher.Add( new KeyValuePair<char, int>( 'b', 553 ) );
cipher.Add( new KeyValuePair<char, int>( 'c', 915 ) );
KeyValuePair<char, int> pair = cipher[ 1 ];
アイテムが追加された順序でリストにとどまることを正しいと仮定すると、提案されたList
ではなくSortedList
を使用できると信じています。
問題は、辞書がソートされていないことです。必要なのは SortedList です。これにより、インデックスだけでなくキーでも値を取得できますが、必要なソートを取得するには、コンストラクターで独自の比較演算子を指定する必要があります。その後、キーと値の順序付きリストにアクセスし、必要に応じてIndexOfKey/IndexOfValueメソッドのさまざまな組み合わせを使用できます。
このような:
int n = 0;
int nthValue = cipher[cipher.Keys.ToList()[n]];
ページの上部にLinqへの参照も必要になることに注意してください...
using System.Linq;
実際にキーで検索する必要がありますか?そうでない場合は、List<KeyValuePair<char, int>>
(さらに良いことに、charとintをカプセル化する型を作成します)。
辞書は本質的にソートされていません-.NETでareにソートされているディクショナリ実装は、挿入順ではなくキーでソートされます。
挿入順序とキーの両方でコレクションにアクセスする必要がある場合、リストと辞書を単一のコレクションタイプにカプセル化することをお勧めします。
または、リストが非常に短い場合は、線形検索を実行するだけでインデックスによる検索を許可します...
次のようにElementAt()
を使用できます。
cipher.ElementAt(index);
Select
オプションよりも優れているのは、この方法では辞書をループする必要がないためです。
/// <summary>Returns the element at a specified index in a sequence.</summary>
/// <returns>The element at the specified position in the source sequence.</returns>
/// <param name="source">An <see cref="T:System.Collections.Generic.IEnumerable`1" /> to return an element from.</param>
/// <param name="index">The zero-based index of the element to retrieve.</param>
/// <typeparam name="TSource">The type of the elements of <paramref name="source" />.</typeparam>
/// <exception cref="T:System.ArgumentNullException">
/// <paramref name="source" /> is null.</exception>
/// <exception cref="T:System.ArgumentOutOfRangeException">
/// <paramref name="index" /> is less than 0 or greater than or equal to the number of elements in <paramref name="source" />.</exception>
辞書の元の仕様に固執するために、私はいくつかのコードを投げて思いついた:
Dictionary<string, string> d = new Dictionary<string, string>();
d.Add("a", "Apple");
d.Add("b", "ball");
d.Add("c", "cat");
d.Add("d", "dog");
int t = 0;
foreach (string s in d.Values)
{
t++;
if (t == 2) Console.WriteLine(s);
}
そして、コンソールに2番目の項目(「ボール」)を繰り返し書き込みます。 n番目の要素を取得するメソッド呼び出しにラップすると、おそらく機能します。しかし、これはかなりいです。 @thecoopが示唆しているように、代わりにSortedListを実行できる場合は、その方が良いでしょう。
ここで尋ねられたこの質問のduがありました: 辞書のN番目のアイテムを取得する方法? 。すぐに閉じる必要がありますが、ここでの回答には新しいOrderedDictionaryクラスがないことがわかりました。
現在(.NET 4以降)、 OrderedDictionary クラスがあります。これにより、順序付けを提供しながら高速検索が可能になります。 Item(Int32)メソッドは、n番目の要素を返します。
次のLINQクエリを「暗号」Dictionary
に適用できます
var cipher = new Dictionary<char, int>();
cipher.Add('a', 324);
cipher.Add('b', 553);
cipher.Add('c', 915);
var nThValue = cipher.Select((Val, Index) => new { Val, Index })
.Single(viPair => viPair.Index == 1) //Selecting dictionary item with it's index using index
.Val //Extracting KeyValuePair from dictionary item
.Value; //Extracting Value from KeyValuePair
これは古い質問ですが、役に立ちました。これが私が使用した実装です。 n番目の要素が挿入順序に基づいていることを望みました。
public class IndexedDictionary<TKey, TValue> : IEnumerable<TValue> {
private List<TValue> list = new List<TValue>();
private Dictionary<TKey, TValue> dict = new Dictionary<TKey, TValue>();
public TValue this[int index] { get { return list[index]; } }
public TValue this[TKey key] { get { return dict[key]; } }
public Dictionary<TKey, TValue>.KeyCollection Keys { get { return dict.Keys; } }
public int Count { get { return list.Count; } }
public int IndexOf(TValue item) { return list.IndexOf(item); }
public int IndexOfKey(TKey key) { return list.IndexOf(dict[key]); }
public void Add(TKey key, TValue value) {
list.Add(value);
dict.Add(key, value);
}
IEnumerator<TValue> IEnumerable<TValue>.GetEnumerator() {
return list.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator() {
return list.GetEnumerator();
}
}