C# .NET 2.0 で、foreach を逆に実行する簡単な方法は何ですか?
-
01-07-2019 - |
質問
Dictionary オブジェクトがあるとします。
Dictionary myDictionary<int, SomeObject> = new Dictionary<string, SomeObject>();
ここで、辞書を逆の順序で繰り返し処理したいと思います。辞書のキーがわからないため、単純な for ループを使用できません。あ フォーリーチ は簡単だ:
foreach (SomeObject object in myDictionary.Values)
{
// Do stuff to object
}
しかし、これを逆に実行するにはどうすればよいでしょうか?
解決
辞書の代わりに SortedList を使用します。引き続きキーでアクセスできますが、インデックスでもアクセスできます。
SortedList sCol = new SortedList();
sCol.Add("bee", "Some extended string matching bee");
sCol.Add("ay", "value matching ay");
sCol.Add("cee", "Just a standard cee");
// Go through it backwards.
for (int i = sCol.Count - 1; i >=0 ; i--)
Console.WriteLine("sCol[" + i.ToString() + "] = " + sCol.GetByIndex(i));
// Reference By Key
foreach (string i in sCol.Keys)
Console.WriteLine("sCol[" + i + "] = " + sCol[i]);
// Enumerate all values
foreach (string i in sCol.Values)
Console.WriteLine(i);
ソートされたリストには、キーのみでソートされたキーと値のペアが格納されることに注意してください。
他のヒント
辞書やその他の形式のハッシュテーブルには順序付けがありません。したがって、あなたがやろうとしていることは無意味です:)
.NET 3.5 を使用している場合は、IEnumerables で .Reverse() 拡張メソッドを使用できます。例えば:
foeach (SomeObject o in myDictionary.Values.Reverse())
{
// Do stuff to object
}
実際、C# 2.0 では、コンテナーを逆に走査する独自のイテレーターを作成できます。その後、そのイテレータを foreach ステートメントで使用できます。ただし、イテレーターには、最初にコンテナーをナビゲートする方法が必要です。単純な配列の場合は、次のように逆方向に進むことができます。
static IEnumerable<T> CreateReverseIterator<T>(IList<T> list)
{
int count = list.Count;
for (int i = count - 1; i >= 0; --i)
{
yield return list[i];
}
}
ただし、Dictionary では IList が実装されておらず、インデクサーも提供されていないため、それを行うことはできません。辞書に順序がないというのは真実ではありません。もちろん秩序があります。この順序は、それが何であるかを知っていればさらに役立ちます。
問題を解決するには:要素を配列にコピーし、上記の方法を使用してそれを逆に走査すると思います。このような:
static void Main(string[] args)
{
Dictionary<int, string> dict = new Dictionary<int, string>();
dict[1] = "value1";
dict[2] = "value2";
dict[3] = "value3";
foreach (KeyValuePair<int, string> item in dict)
{
Console.WriteLine("Key : {0}, Value: {1}", new object[] { item.Key, item.Value });
}
string[] values = new string[dict.Values.Count];
dict.Values.CopyTo(values, 0);
foreach (string value in CreateReverseIterator(values))
{
Console.WriteLine("Value: {0}", value);
}
}
値を配列にコピーするのは悪い考えのように思えるかもしれませんが、値の種類によっては、それほど悪いことではありません。参考文献をコピーしているだけかもしれません。
私は @leppie さんの意見に同意しますが、一般的な質問にはあなたが答える価値があると思います。一般的な質問のつもりが、間違って間違ったデータ構造を選んでしまった可能性があります。ディクショナリ内の値の順序は実装固有であると考慮する必要があります。ドキュメントによると、キーの順序は常に同じですが、この順序も指定されていません。
いずれにせよ、簡単に作る方法はありません foreach
逆に働きます。これはクラスの列挙子を使用するための糖衣構文であり、列挙子は一方向にのみ移動できます。技術的には、答えは「コレクションを逆にして列挙する」ということになるかもしれませんが、これは単に「逆方向」の for ループを使用する必要があるケースだと思います。
for (int i = myCollection.Length - 1; i >= 0; i--)
{
// do something
}
.NET 3.5 がない場合、つまり Reverse 拡張メソッドがない場合は、独自のメソッドを実装できます。おそらく、次のような中間リストを (必要に応じて) 生成し、それを逆に反復するのではないかと思います。
public static IEnumerable<T> Reverse<T>(IEnumerable<T> items)
{
IList<T> list = items as IList<T>;
if (list == null) list = new List<T>(items);
for (int i = list.Count - 1; i >= 0; i-- )
{
yield return list[i];
}
}
それは Dictionary<int, SomeObject> myDictionary
, 、次のようにして実行します。
foreach(SomeObject _object in myDictionary.Values.Reverse())
{
}
私が思いつく唯一の方法は .NET 2.0 まずすべての値をリストにコピーし、リストを反転してから、そのリストに対して foreach を実行します。
Dictionary<int, object> d;
List<object> tmplist;
foreach (object o in d.Values) tmplist.Add(s);
tmplist.Reverse();
foreach (object o in tmplist) {
//Do stuff
}
順序が最も重要な場合は、スタックを作成し、int と Object のペアを格納する単純な構造体を作成できます。
標準 for
ループがベストでしょう。コレクションを元に戻す処理のオーバーヘッドを心配する必要はありません。
使用できます オブジェクトへの LINQ .NET 2.0 の Enumerable.Reverse() 関数を使用する リンクブリッジ.
文字通りの答え:
Dictionary<int, SomeObject> myDictionary = new Dictionary<int, SomeObject>();
foreach (var pair in myDictionary.OrderByDescending(i => i.Key))
{
//Observe pair.Key
//Do stuff to pair.Value
}
foreach (Sample in Samples)
try the following:
Int32 nEndingSample = Samples.Count - 1;
for (i = nEndingSample; i >= 0; i--)
{
x = Samples[i].x;
y = Samples[i].y;
}