【发布时间】:2021-08-07 14:35:13
【问题描述】:
总结:在将 Linq OrderBy 与比较器一起使用时,我看到 OrderBy 将项目与自身进行比较 Compare (x, x),并且我看到它多次比较相同的项目 Comparer (x, y)。
- 为什么 OrderBy
Compare (x, x)? - 为什么 OrderBy 会多次比较同一商品?
问题描述
如果你有一个(可能是空的)项目序列,并且你想要最大的一个,你可以使用OrderBy(...).FirstOrDefault()。
我想,如果您只使用最大的一件,订购数千件商品会浪费处理能力。您可以尝试通过创建某种Max 方法在一个枚举中找到这个最大的元素。
同样,如果您搜索最大的几个元素:为什么要对所有项目进行排序?
我听到有人说,如果你使用 OrderBy 并且只取第一个元素,那么就不是完整的序列。
所以我想创建一个测试程序,在其中使用客户比较器订购客户。要查看哪些客户是比较者,客户比较者会将客户的 Id 写入控制台。
class Customer
{
public int Id {get; set;}
...
}
class CustomerComparer : Comparer<Customer>
{
public override int Compare(Customer x, Customer y)
{
int result = Comparer<int>.Default(x.Id, y.Id);
Console.WriteLine("Compare {0} - {1} => {2}", x.Id, y.Id, result);
return result;
}
}
控制台程序
static void Main(string[] args)
{
var customers = new[]
{
new Customer {Id = 2},
new Customer {Id = 9},
new Customer {Id = 6},
new Customer {Id = 1},
new Customer {Id = 4},
new Customer {Id = 7},
new Customer {Id = 3},
new Customer {Id = 8},
new Customer {Id = 5},
};
IComparer<Customer> comparer = new CustomerComparer;
var result = customers.OrderBy(customer => customer, customerComparer).FirstOrDefault();
如果我运行程序,我会得到以下输出:
Compare 4 - 2 => 1
Compare 4 - 9 => -1
Compare 4 - 5 => -1
Compare 4 - 8 => -1
Compare 4 - 3 => 1
Compare 4 - 6 => -1
Compare 4 - 7 => -1
Compare 4 - 4 => 0
Compare 4 - 1 => 1
Compare 4 - 6 => -1
Compare 4 - 1 => 1
Compare 3 - 2 => 1
Compare 3 - 3 => 0
Compare 3 - 1 => 1
Compare 3 - 4 => -1
Compare 3 - 4 => -1
Compare 3 - 1 => 1
Compare 2 - 2 => 0
Compare 2 - 1 => 1
Compare 4 - 4 => 0
Compare 4 - 3 => 1
Compare 9 - 6 => 1
Compare 9 - 7 => 1
Compare 9 - 9 => 0
Compare 9 - 5 => 1
Compare 9 - 8 => 1
Compare 9 - 9 => 0
Compare 9 - 8 => 1
Compare 7 - 6 => 1
Compare 7 - 7 => 0
Compare 7 - 8 => -1
Compare 7 - 5 => 1
Compare 6 - 6 => 0
Compare 6 - 5 => 1
Compare 7 - 7 => 0
Compare 7 - 8 => -1
Compare 7 - 7 => 0
我看到了一些奇怪的东西:
- 客户 [4] 与其自身进行了多次比较。这也适用于客户 [7] 和 [6],但不适用于客户 [8] 和 [1]
- 将客户 [4] 与客户 [6] 进行比较,经过几次比较后,再次将客户 [4] 与客户 [6] 进行比较。
- 客户 [3] 和 [4] 被比较两次,中间没有任何其他比较。
- 双重比较也适用于客户 [4] 和 [1],稍后适用于 [4] 和 [3],但不适用于其他客户
为什么这是一种高效的排序算法?
【问题讨论】:
-
对于基于比较的排序算法,比较通常被认为是廉价的(与重新排列元素相反)。当然可以清除冗余比较或缓存它们(以空间换时间),但这通常会降低性能。很少有排序算法能保证最小必要的比较次数,而不是一个数量级。
标签: c# performance linq sorting