按顺序选择所有元素的索引

时间:2013-05-01 19:45:51

标签: c# linq select indexing

使用LINQ,我可以编写一个语句来返回项目索引的IEnumerable。

非常简单的实例:

{1,2,4,5,3}

只会返回

{0,1,2,3,4}

{1,2,4,5,3}.Where(num => num == 4)

将返回

{2}

这不是确切的代码,但它应该让我们了解这个想法。

7 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:0)

如果您愿意稍微更改语法并使用扩展方法,则以下内容将起作用。我并不热衷于它,因为它为每次通话创建了一个新序列。

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}

答案 2 :(得分:0)

var numbers = Enumerable.Range(1,10).ToList();

int index = -1;

var indices = numbers.Select(x => i++).ToList();

答案 3 :(得分:0)

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;

答案 4 :(得分:0)

完整的索引集取决于项目的数量,而不是取决于值,因此您可以这样做:

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]

如果谓词与任何值都不匹配,那么你将获得一个空的可枚举值。

答案 5 :(得分:0)

你可以这样做:

public static IEnumerable<int> WhereIndices<T>(this IEnumerable<T> source, Func<T, bool> predicate)
{
    return source.Select(Tuple.Create<T, int>)
        .Where(z => predicate(z.Item1)).Select(z => z.Item2);
}

这是一个扩展方法,所以把它放在一个静态的非嵌套类中。像使用Where一样使用它,即:

.WhereIndices(num => num == 4)

答案 6 :(得分:-1)

这应该这样做。不确定它有多高效..

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