我有一个问题需要有效解决。
我需要IEnumerable源中元素的索引,我可以通过以下方式执行此操作
var items = source.Cast<ObjectType>().Where(obj => obj.Start == forDate);
这将为我提供与谓词匹配的所有项目的IEnumerable。
if(items != null && items.Any()){
// I now need the ordinal from the original list
return source.IndexOf(items[0]);
}
然而,列表可能很大,操作将进行多次。我认为这是低效的,必须有更好的方法来做到这一点。
如果有人能指出我正确的方向,我将不胜感激。
答案 0 :(得分:2)
有时,忘记Linq并回归基础会很好:
int index = 0;
foeach (ObjectType element in source)
{
if (element.Start == forDate)
{
return index;
}
index++;
}
// No element found
答案 1 :(得分:2)
使用Linq,您可以在过滤之前获取每个对象的索引:
source
.Cast<ObjectType>()
.Select((obj, i) => new { Obj = obj, I = i })
.Where(x => x.Obj.Start == forDate)
.Select(x => x.I)
.FirstOrDefault();
然而,这并不是真正有效的,以下将在没有分配的情况下做同样的事情:
int i = 0;
foreach (ObjectType obj in source)
{
if (obj.Start == forDate)
{
return i;
}
i++;
}
答案 2 :(得分:1)
您的第二个代码示例无效:由于items
是IEnumerable
,因此您无法调用items[0]
。您可以使用First()
。无论如何:
var items = source.Cast<ObjectType>()
.Select((item, index) => new KeyValuePair<int, ObjectType>(index, item))
.Where(obj => obj.Value.Start == forDate);
然后:
if (items != null && items.Any()) {
return items.First().Key;
}
答案 3 :(得分:1)
如果你需要多次这样做,我会为索引创建一个查找。
ILookup<DateTime, int> lookup =
source
.Cast<ObjectType>()
.Select((e, i) => new { e, i })
.ToLookup(x => x.e.Start, x => x.i);
现在给出forDate
你可以这样做:
IEnumerable<int> indices = lookup[forDate];
由于lookup
基本上类似于返回多个值的字典,因此您可以立即获得结果。因此,对多个值重复此操作非常快。
由于这会返回IEnumerable<int>
,因此您知道source
列表中何时存在重复值。如果您只需要第一个,那么只需.First()
。