LINQ を使用して、項目のインデックスの IEnumerable を返すステートメントを記述できますか。
非常に単純な例:
{1,2,4,5,3}
ただ戻るだろう
{0,1,2,3,4}
と
{1,2,4,5,3}.Where(num => num == 4)
戻るだろう
{2}
これは正確なコードではありませんが、アイデアが伝わるはずです。
var a = new[] {1, 2, 4, 5, 3};
//** First, generates a simple sequence with {0,1,2,3,4}
//** using the 2 parameter lambda select
var sequence1 = a.Select((_, index) => index);
//** Second, gets an array with all indexes where the value is 4.
// We need both value and index for the next line to work.
var sequence2 = a.Select((value, index) => new {value, index});
// Get all indexes where the value is 4
var indexArray = sequence2.Where(x => x.value == 4)
.Select(x => x.index).ToArray();
var numbers = Enumerable.Range(1,10).ToList();
int index = -1;
var indices = numbers.Select(x => i++).ToList();
構文を少し変更して拡張メソッドを使用する場合は、次のようにします。呼び出しごとに新しいシーケンスが作成されるため、私はそれに熱心ではありません。
var sequence = new[] { 1, 2, 4, 5, 3 };
sequence.Indexer().Select(num => num.Item1); // returns {0,1,2,3,4}
sequence.Indexer().Where(num => num.Item2 == 4).Select(num => num.Item1); // returns {2}
private static IEnumerable<Tuple<int, T>> Indexer<T>(this IEnumerable<T> sequence)
{
return sequence.Select((x, y) => new Tuple<int, T>(y, x));
}
より良い方法は、書き方を完全に変更することです。
var sequence = new[] { 1, 2, 4, 5, 3 };
sequence.Select((num, index) => new { Num = num, Index = index }).Select(num => num.Index); // returns {0, 1,2,3,4}
sequence.Select((num, index) => new { Num = num, Index = index }).Where(num => num.Num == 4).Select(num => num.Index); // returns {2}
インデックスの完全なセットは、値ではなくアイテムの数に依存するため、次のようにすることができます。
IEnumerable<int> indices = Enumerable.Range(0, 5);
を扱っている場合IEnumerable<T>
、次のようにして 4 に一致するアイテムのインデックスを取得できます。
IEnumerable<int> values = new[] { 1, 2, 3, 4, 5 };
int indexOf4 = (
values.Select((v, i) => new {v, i})
.FirstOrDefault(vi => vi.v == 4) ?? new {v = 0, i = -1}).i;
これは、値のソースに一致が含まれていない場合 (-1 を返す) に対処します。
もちろん、IEnumerable<T>
リストへの変換を気にしない場合は、次のように呼び出すことができますIndexOf
。
int indexOf4a = values.ToList().IndexOf(4);
しかし、質問が実際に探しているのは、特定の述語に一致する値のすべてのインデックスを見つける方法だと思います。例えば:
IEnumerable<int> big = values.Select((v, i) => new {v, i})
.Where(vi => vi.v > 3)
.Select (vi => vi.i);
値のインデックスを返します> 3
: [3, 4]
.
述語がどの値とも一致しない場合、結果として空の列挙型が得られます。
IEnumerable<int> seq = new[] { 1, 2, 4, 5, 3 };
// The indexes of all elements.
var indexes = Enumerable.Range(0, seq.Count());
// The index of the left-most element with value 4.
// NOTE: Will return seq.Count() if the element doesn't exist.
var index = seq.TakeWhile(x => x != 4).Count();
// The indexes of all the elements with value 4.
// NOTE: Be careful to enumerate only once.
int current_index = 0;
var all_indexes =
from e in (
from x in seq
select new { x, Index = current_index++ }
)
where e.x == 4
select e.Index;
これでうまくいくはずです。それがどれほど効率的かはわかりませんが..
List<int> list = new List<int>()
{
1,
2,
3,
4,
5
};
var indexes = list.Select(item => list.IndexOf(item));
var index = list.Where(item => item == 4).Select(item => list.IndexOf(item));