C# 查询IEnumerable作为IEnumerable<;类型>;
我有一个问题需要有效地解决 我需要IEnumerable源中元素的索引,一种方法是使用下面的C# 查询IEnumerable作为IEnumerable<;类型>;,c#,linq,xamarin,C#,Linq,Xamarin,我有一个问题需要有效地解决 我需要IEnumerable源中元素的索引,一种方法是使用下面的 var items = source.Cast<ObjectType>().Where(obj => obj.Start == forDate); 然而,名单可能是巨大的,行动将进行多次。我认为这是低效的,必须有更好的方法来做到这一点 如果有人能为我指出正确的方向,我将不胜感激。有时候,最好忘记Linq,回到最基本的方面: int index = 0; foeach (Ob
var items = source.Cast<ObjectType>().Where(obj => obj.Start == forDate);
然而,名单可能是巨大的,行动将进行多次。我认为这是低效的,必须有更好的方法来做到这一点
如果有人能为我指出正确的方向,我将不胜感激。有时候,最好忘记Linq,回到最基本的方面:
int index = 0;
foeach (ObjectType element in source)
{
if (element.Start == forDate)
{
return index;
}
index++;
}
// No element found
有时候,最好忘记Linq,回到最基本的方面:
int index = 0;
foeach (ObjectType element in source)
{
if (element.Start == forDate)
{
return index;
}
index++;
}
// No element found
使用Linq,可以在过滤每个对象之前获取它们的索引:
source
.Cast<ObjectType>()
.Select((obj, i) => new { Obj = obj, I = i })
.Where(x => x.Obj.Start == forDate)
.Select(x => x.I)
.FirstOrDefault();
使用Linq,可以在过滤每个对象之前获取它们的索引:
source
.Cast<ObjectType>()
.Select((obj, i) => new { Obj = obj, I = i })
.Where(x => x.Obj.Start == forDate)
.Select(x => x.I)
.FirstOrDefault();
您的第二个代码示例无效:由于
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);
您的第二个代码示例无效:由于
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);
如果您需要多次执行此操作,我将创建索引查找
ILookup<DateTime, int> lookup =
source
.Cast<ObjectType>()
.Select((e, i) => new { e, i })
.ToLookup(x => x.e.Start, x => x.i);
由于查找
基本上类似于返回多个值的字典,因此您可以立即得到结果。因此,对多个值重复此操作非常快
由于这将返回
IEnumerable
,因此您知道源
列表中何时存在重复值。如果您只需要第一个,那么只需执行.first()
如果您需要多次执行此操作,我将创建索引的查找
ILookup<DateTime, int> lookup =
source
.Cast<ObjectType>()
.Select((e, i) => new { e, i })
.ToLookup(x => x.e.Start, x => x.i);
由于查找
基本上类似于返回多个值的字典,因此您可以立即得到结果。因此,对多个值重复此操作非常快
由于这将返回
IEnumerable
,因此您知道源
列表中何时存在重复值。如果您只需要第一个,那么只需执行一个.first()
您无法有效地使用IEnumerable
执行此操作。这就是为什么我们有其他接口,比如ICollection
。例如,IEnumerable
可以通过数据库连接/ORM实现,也可以通过LinkedList实现。这两种方法都不能实现有效的算法。@Aron-但是,如果基础类型也是ICollection
,那么LINQ会在可能的情况下使用有效的方法。感谢所有发布答案的人。很多都是未来很好的参考。但是,在本例中,由于实现的特殊性,我实现了一个二进制搜索。这就是为什么我们有其他接口,比如ICollection
。例如,IEnumerable
可以通过数据库连接/ORM实现,也可以通过LinkedList实现。这两种方法都不能实现有效的算法。@Aron-但是,如果基础类型也是ICollection
,那么LINQ会在可能的情况下使用有效的方法。感谢所有发布答案的人。很多都是未来很好的参考。但是,在本例中,由于实现的细节,我实现了二进制搜索。为什么使用KeyValuePair(index,item)
?为什么不仅仅是new{index,item}
?@Enigmativity,因为它是一个结构,而是您喜欢的任何东西。我想这并不重要。struct
为什么有帮助?@Enigmativity在这种情况下,这并不重要,因为你只拿了第一项。但是,如果你要枚举一百万个项目,它将避免创建一百万个对象。(我使用了KeyValuePair
,这是一种反射,我没有考虑使用匿名类型)请记住KeyValuePair
没有实现Equals
&GetHashCode
,因此它不能用于许多需要比较的运算符。匿名类型确实实现了它们。最好避免使用KeyValuePair
。为什么要使用KeyValuePair(索引,项目)
?为什么不仅仅是new{index,item}
?@Enigmativity,因为它是一个结构,而是您喜欢的任何东西。我想这并不重要。struct
为什么有帮助?@Enigmativity在这种情况下,这并不重要,因为你只拿了第一项。但是,如果你要枚举一百万个项目,它将避免创建一百万个对象。(我使用了KeyValuePair
,这是一种反射,我没有考虑使用匿名类型)请记住KeyValuePair
没有实现Equals
&GetHashCode
,因此它不能用于许多需要比较的运算符。匿名类型确实实现了它们。最好避免使用KeyValuePair
。对,将它们编入索引。这与ToDictionary()有何不同?@bit-它的不同之处在于字典仅将键映射到单个值,而这将任何键映射到零或多个值(从而获得重复值的所有索引)。如果使用不存在的键进行查找,则会得到一个空的可枚举项,而不是一个异常。这与ToDictionary()有何不同?@bit-它的不同之处在于字典仅将键映射到单个值,而这将任何键映射到零或多个值(从而获得重复值的所有索引)。如果使用不存在的键执行查找,则会得到一个空的可枚举项,而不是一个异常。我已经实现了二进制搜索,这可以避免将列表中的所有项强制转换为所需类型的需要,并减少操作的内存开销。有时最好忘记Linq。我实现了一个二进制搜索,这样可以避免将列表中的所有项强制转换为所需的类型,并减少操作的内存开销。有时候忘记林克是件好事。