将IEnumerable查询为IEnumerable <type>

时间:2016-03-10 09:21:52

标签: c# linq xamarin

我有一个问题需要有效解决。

我需要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]);
   }

然而,列表可能很大,操作将进行多次。我认为这是低效的,必须有更好的方法来做到这一点。

如果有人能指出我正确的方向,我将不胜感激。

4 个答案:

答案 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)

您的第二个代码示例无效:由于itemsIEnumerable,因此您无法调用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()