LINQ 中的隐式索引或生成索引
Implicit Index or Generating Index in LINQ
我最近遇到几个案例,这让我想知道是否有任何方法可以获取内部索引,或者如果没有,可以在使用 LINQ 时有效地生成索引。
考虑以下情况:
List<int> list = new List() { 7, 4, 5, 1, 7, 8 };
在 C# 中,如果我们要使用 LINQ return 上述数组中“7”的索引,我们不能简单地使用 IndexOf/LastIndexOf - 因为它只会 return first/last 结果。
这行不通:
var result = list.Where(x => x == 7).Select(y => list.IndexOf(y));
但是,我们有几种解决方法。
例如,一种方法可能是这样(我通常这样做):
int index = 0;
var result = from x in list
let indexNow = index++
where x == 7
select indexNow;
使用let会引入额外的参数indexNow。
还有另一种方式:
var result = Enumerable.Range(0, list.Count).Where(x => list.ElementAt(x) == 7);
它将使用Enumerable.Range生成另一组项目并从中选择结果。
现在,我想知道是否有更简单的替代方法,例如:
- 如果有任何(内置)方法可以获取 IEnumerable 的内部索引而无需使用 let 或
声明某些内容
- 使用 Enumerable.Range 以外的东西为 IEnumerable 生成索引(也许像新的东西?我不太熟悉如何去做),或者
- 任何其他可以缩短代码但仍然获得 IEnumerable 索引的东西。
来自 IEnumerable.Select with index, How to get index using LINQ?, and so on: IEnumerable<T>.Select()
has an overload that provides an index。
使用它,您可以:
- 投射到包含索引和值的匿名类型(或者
Tuple<int, T>
如果您想将其公开给其他方法,匿名类型是本地的)。
- 根据您要查找的值过滤这些结果。
- 仅投影索引。
因此代码将如下所示:
var result = list.Select((v, i) => new { Index = i, Value = v })
.Where(i => i.Value == 7)
.Select(i => i.Index);
现在 result
将包含一个包含所有索引的枚举。
请注意,这仅适用于保证插入顺序并提供数字索引器的源集合类型,例如 List<T>
。当您将此用于 Dictionary<TKey, TValue>
或 HashSet<T>
时,生成的索引将无法用于索引到字典中。
我最近遇到几个案例,这让我想知道是否有任何方法可以获取内部索引,或者如果没有,可以在使用 LINQ 时有效地生成索引。
考虑以下情况:
List<int> list = new List() { 7, 4, 5, 1, 7, 8 };
在 C# 中,如果我们要使用 LINQ return 上述数组中“7”的索引,我们不能简单地使用 IndexOf/LastIndexOf - 因为它只会 return first/last 结果。
这行不通:
var result = list.Where(x => x == 7).Select(y => list.IndexOf(y));
但是,我们有几种解决方法。
例如,一种方法可能是这样(我通常这样做):
int index = 0;
var result = from x in list
let indexNow = index++
where x == 7
select indexNow;
使用let会引入额外的参数indexNow。
还有另一种方式:
var result = Enumerable.Range(0, list.Count).Where(x => list.ElementAt(x) == 7);
它将使用Enumerable.Range生成另一组项目并从中选择结果。
现在,我想知道是否有更简单的替代方法,例如:
- 如果有任何(内置)方法可以获取 IEnumerable 的内部索引而无需使用 let 或 声明某些内容
- 使用 Enumerable.Range 以外的东西为 IEnumerable 生成索引(也许像新的东西?我不太熟悉如何去做),或者
- 任何其他可以缩短代码但仍然获得 IEnumerable 索引的东西。
来自 IEnumerable.Select with index, How to get index using LINQ?, and so on: IEnumerable<T>.Select()
has an overload that provides an index。
使用它,您可以:
- 投射到包含索引和值的匿名类型(或者
Tuple<int, T>
如果您想将其公开给其他方法,匿名类型是本地的)。 - 根据您要查找的值过滤这些结果。
- 仅投影索引。
因此代码将如下所示:
var result = list.Select((v, i) => new { Index = i, Value = v })
.Where(i => i.Value == 7)
.Select(i => i.Index);
现在 result
将包含一个包含所有索引的枚举。
请注意,这仅适用于保证插入顺序并提供数字索引器的源集合类型,例如 List<T>
。当您将此用于 Dictionary<TKey, TValue>
或 HashSet<T>
时,生成的索引将无法用于索引到字典中。