web-dev-qa-db-ja.com

インデックス付きforeach

Pythonのenumerate()およびRubyのeach_with_indexに相当するC#はありますか?

150
Ken

私はこのためにこの拡張メソッドを保持します:

public static void Each<T>(this IEnumerable<T> ie, Action<T, int> action)
{
    var i = 0;
    foreach (var e in ie) action(e, i++);
}

そして次のように使用します:

var strings = new List<string>();
strings.Each((str, n) =>
{
    // hooray
});

または、breakのような動作を許可するには:

public static bool Each<T>(this IEnumerable<T> ie, Func<T, int, bool> action)
{
    int i = 0;
    foreach (T e in ie) if (!action(e, i++)) return false;
    return true;
}

var strings = new List<string>() { "a", "b", "c" };

bool iteratedAll = strings.Each ((str, n)) =>
{
    if (str == "b") return false;
    return true;
});
258
Dan

次のことができます

foreach (var it in someCollection.Select((x, i) => new { Value = x, Index = i }) )
{
   if (it.Index > SomeNumber) //      
}

これにより、コレクトのすべてのエントリに匿名型の値が作成されます。 2つのプロパティがあります

  1. 値:コレクション内の元の値
  2. インデックス:コレクション内のインデックス付き
199
JaredPar

C#foreachには組み込みのインデックスがありません。 foreachループの外側に整数を追加し、毎回インクリメントする必要があります。

int i = -1;
foreach (Widget w in widgets)
{
   i++;
   // do something
}

または、次のように標準forループを使用できます。

for (int i = 0; i < widgets.Length; i++)
{
   w = widgets[i];
   // do something
}
59
David Morton

私はforeachを使用できるのが好きなので、拡張メソッドと構造を作成しました。

public struct EnumeratedInstance<T>
{
    public long cnt;
    public T item;
}

public static IEnumerable<EnumeratedInstance<T>> Enumerate<T>(this IEnumerable<T> collection)
{
    long counter = 0;
    foreach (var item in collection)
    {
        yield return new EnumeratedInstance<T>
        {
            cnt = counter,
            item = item
        };
        counter++;
    }
}

および使用例:

foreach (var ii in new string[] { "a", "b", "c" }.Enumerate())
{
    Console.WriteLine(ii.item + ii.cnt);
}

良い点の1つは、Python構文に慣れている場合でも使用できることです。

foreach (var ii in Enumerate(new string[] { "a", "b", "c" }))
16
Daniel K

既に与えられたLINQの答えとは別に、 "SmartEnumerable" クラスがあります。これにより、インデックスと "first/last" -nessを取得できます。構文の面では少しugいですが、役に立つかもしれません。

非ジェネリック型の静的メソッドを使用して、おそらく型推論を改善できます。また、暗黙的な型指定も役立ちます。

15
Jon Skeet

私のソリューションには、汎用ユーティリティ用に作成した単純なPairクラスが含まれます。これは、操作上、フレームワーククラスKeyValuePairと本質的に同じです。次に、Ordinateと呼ばれるIEnumerableの拡張関数をいくつか作成しました(集合理論用語 " ordinal "から)。

これらの関数は、各アイテムに対して、インデックスを含むPairオブジェクトとアイテム自体を返します。

public static IEnumerable<Pair<Int32, X>> Ordinate<X>(this IEnumerable<X> lhs)
{
    return lhs.Ordinate(0);
}

public static IEnumerable<Pair<Int32, X>> Ordinate<X>(this IEnumerable<X> lhs, Int32 initial)
{
    Int32 index = initial - 1;

    return lhs.Select(x => new Pair<Int32, X>(++index, x));
}
6
Chris Ammerman

いいえ、ありません。

他の人が示したように、Rubyの動作をシミュレートする方法があります。しかし、インデックスを公開しない IEnumerable を実装する型を持つことは可能です。

3
Darryl Braaten

これはあなたのコレクションです

var values = new[] {6, 2, 8, 45, 9, 3, 0};

このコレクションのインデックスの範囲を作成します

var indexes = Enumerable.Range(0, values.Length).ToList();

範囲を使用してインデックスで反復処理する

indexes.ForEach(i => values[i] += i);
indexes.ForEach(i => Console.Write("[{0}] = {1}", i, values[i]));
1
vonWippersnap

私はちょうど面白い解決策を見つけました:

public class DepthAware<T> : IEnumerable<T>
{
    private readonly IEnumerable<T> source;

    public DepthAware(IEnumerable<T> source)
    {
        this.source = source;
        this.Depth = 0;
    }

    public int Depth { get; private set; }

    private IEnumerable<T> GetItems()
    {
        foreach (var item in source)
        {
            yield return item;
            ++this.Depth;
        }
    }

    public IEnumerator<T> GetEnumerator()
    {
        return GetItems().GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}

// Generic type leverage and extension invoking
public static class DepthAware
{
    public static DepthAware<T> AsDepthAware<T>(this IEnumerable<T> source)
    {
        return new DepthAware<T>(source);
    }

    public static DepthAware<T> New<T>(IEnumerable<T> source)
    {
        return new DepthAware<T>(source);
    }
}

使用法:

var chars = new[] {'a', 'b', 'c', 'd', 'e', 'f', 'g'}.AsDepthAware();

foreach (var item in chars)
{
    Console.WriteLine("Char: {0}, depth: {1}", item, chars.Depth);
}
1
Pz.

使用しているクラスによって異なります。

Dictionary <(Of <(TKey、TValue>)>)例のクラスはこれをサポートします

Dictionary <(Of <(TKey、TValue>)>)ジェネリッククラスは、キーのセットから値のセットへのマッピングを提供します。

列挙のために、ディクショナリ内の各アイテムは、値とそのキーを表すKeyValuePair <(Of <(TKey、TValue>)>)構造体として扱われます。アイテムが返される順序は定義されていません。

foreach(myDictionaryのKeyValuePair kvp){...}

0
VBNight