我有一些代码根据过滤器值过滤排序对象的集合。例如,我想找到Name=="searchquery"
的对象。然后我想从该集合中获取前X个值。
我的问题:
我的收藏是List<T>
。此集合是否保证排序顺序?
如果是这样,是否有内置的方法来查找满足条件的前X个对象?我正在寻找像
这样的东西collection.FindAll(o=>o.Name=="searchquery",100);
这会给我满足条件的前100个对象。原因是性能,一旦我找到了100个对象,我不想继续检查整个集合。
如果我写:
collection.FindAll(o=>o.Name=="searchquery").Take(100);
运行时是否足够智能,一旦达到100就停止检查?
我当然可以自己实现,但如果有内置方式(比如LInQ方法),我宁愿使用它。
答案 0 :(得分:4)
collection.Where(o=>o.Name=="searchquery").Take(100)
顺序应与原始列表的顺序相同,一旦需要100个元素,它将停止检查(Where
返回枚举,该枚举仅在您获取元素时进行评估)。来自the documentation:
此方法通过使用延迟执行来实现。立即返回值是一个对象,它存储执行操作所需的所有信息。在通过直接调用其GetEnumerator方法或在Visual C#中使用foreach或在Visual Basic中使用For Each来枚举对象之前,不会执行此方法表示的查询。
如果您需要不同的排序顺序,则必须指定它(这当然意味着您别无选择,只能检查所有元素)。
答案 1 :(得分:1)
确定,
我的收藏是List<T>
。此集合是否保证排序顺序?
不,但它会保留插入顺序。
如果是这样,是否有内置的方法来查找满足条件的前X个对象?
someEnumerable.Where(r => r.Name == "searchquery").Take(100)
如果我写:
// Some linq that works
运行时是否足够聪明,一旦达到100就停止检查?
是的,可能是
现在,如果您已经排序了IList
,并且想要快速迭代前100个项目,请执行此操作。
var list = sourceEnumerable.OrderBy(r => r.Name).ToList();
foreach(var r in list.Where(r => r.Name == "searchquery").Take(100))
{
// Do something
}
答案 2 :(得分:1)
collection.Where(o=>o.Name=="searchquery").Take(100)
是最正确的答案,因为在幕后Where
是延迟执行,下面是Where
方法的实现方式:
Where(this IEnumerable<T>, Func<T, bool> func)
{
foreach (var item in collection)
{
if (func(item))
{
yield return item;
}
}
}
因此,当调用Take(100)
时,循环只会找到满足条件的前100个项目。
答案 3 :(得分:1)
如果您确定不会重复集合中的对象(例如主键),则可以使用SortedList而不是List<T>
。这将保证,当您使用特定条件过滤列表时,您的列表将被排序。看一下排序列表示例:
http://msdn.microsoft.com/en-us/library/system.collections.sortedlist(v=vs.100).aspx