我是一个完整的 LINQ 新手,所以我不知道我的 LINQ 是否不适合我需要做的事情,或者我对性能的期望是否过高。
我有一个对象的 SortedList,由 int 键控; SortedList 而不是 SortedDictionary,因为我将使用预先排序的数据填充集合。我的任务是找到确切的 key ,或者如果没有确切的 key ,则找到具有下一个更高值的 key 。如果搜索对于列表而言太高(例如最高键是 100,但搜索 105),则返回 null。
// The structure of this class is unimportant. Just using
// it as an illustration.
public class CX
{
public int KEY;
public DateTime DT;
}
static CX getItem(int i, SortedList<int, CX> list)
{
var items =
(from kv in list
where kv.Key >= i
select kv.Key);
if (items.Any())
{
return list[items.Min()];
}
return null;
}
给定一个包含 50,000 条记录的列表,调用 getItem 500 次大约需要 1.5 秒。调用它 50,000 次需要超过 2 分钟。这个性能看起来很差。我的 LINQ 不好吗?我期待太多了吗?我应该推出自己的二进制搜索功能吗?
最佳答案
首先,您的查询将被评估两次(一次针对 Any
,一次针对 Min
)。其次,Min
要求它遍历整个列表,即使它已排序这一事实意味着第一项将是最小值。你应该能够改变这个:
if (items.Any())
{
return list[items.Min()];
}
对此:
var default =
(from kv in list
where kv.Key >= i
select (int?)kv.Key).FirstOrDefault();
if(default != null) return list[default.Value];
return null;
更新
因为您选择的是值类型,FirstOrDefault
不会返回可为 null 的对象。我已更改您的查询以将所选值转换为 int?
,从而允许检查结果值是否为 null
。我会提倡使用 ContainsKey
,因为如果您的列表包含 0
的值,它将返回 true
。例如,假设您有以下值
0 2 4 6 8
如果您要传递小于或等于 8 的任何值,那么您将获得正确的值。但是,如果您传入 9,您将得到 0 (default(int)
),它在列表中,但不在 一个有效的结果。
关于c# - LINQ 到排序列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2897749/