我自己的 OrderBy 函数

发布于 2024-12-14 21:10:32 字数 1050 浏览 0 评论 0原文

我正在编写一段代码,它将根据照片的评级对照片列表进行排序。每张照片都存储在数据库中,每张照片都有正面票数和负面票数等信息。我想按照我计算赞成票百分比的公式对它们进行排序,第一张照片是百分比最高的照片。

为此,我使用了标准 IComparer 接口,并编写了自己的 Comparer 函数,用于比较两张照片。问题是我必须首先从数据库下载所有照片的列表。这似乎是我想避免的很多不必要的努力。所以我想知道是否可以创建自己的 SQL 函数来在数据库端进行比较,并只返回我想要的照片?比在服务器端比较所有照片效率更高?

我自己的比较器的代码:

public class PictureComparer : IComparer<Picture>
{
    public int Compare(Picture p1, Picture p2)
    {
        double firstPictureScore = (((double)p1.PositiveVotes/(double)(p1.PositiveVotes+p1.NegativeVotes))*100);
        double secondPictureScore = (((double)p2.PositiveVotes / (double)(p2.PositiveVotes + p2.NegativeVotes)) * 100);
        if (firstPictureScore < secondPictureScore) return 1;
        if (firstPictureScore > secondPictureScore) return -1;
        return 0;
    }
}

以及使用 comaprer 的代码:

 var pictures = db.Pictures.Include(q => q.Tags).Include(q => q.User).ToList();
 pictures = pictures.OrderBy(q => q, new PictureComparer()).Skip(0 * 10).Take(10).ToList();

I am writing a piece of code which is going to order the list of photos based on their rating. Each photo is stored in DB, and each has such information as number of positive and negative votes. I want to order them by the formula in which I count the percentage of positive votes, and the first photo is the one with the highest percentage.

For that I used the standard IComparer interface, and wrote my own Comparer function, which compares two photos. The problem is that I do that I have to first download the list of all photos from the db. It seems like a lot of unnecessary effort which I would like to avoid. So I am wondering if it is possible to create my own SQL function which will do the comparing on the DB side, and returns to me just the photos I want? It is more efficient than comparing all the photos on the server side?

The code for my own comparer:

public class PictureComparer : IComparer<Picture>
{
    public int Compare(Picture p1, Picture p2)
    {
        double firstPictureScore = (((double)p1.PositiveVotes/(double)(p1.PositiveVotes+p1.NegativeVotes))*100);
        double secondPictureScore = (((double)p2.PositiveVotes / (double)(p2.PositiveVotes + p2.NegativeVotes)) * 100);
        if (firstPictureScore < secondPictureScore) return 1;
        if (firstPictureScore > secondPictureScore) return -1;
        return 0;
    }
}

And the code which uses the comaprer:

 var pictures = db.Pictures.Include(q => q.Tags).Include(q => q.User).ToList();
 pictures = pictures.OrderBy(q => q, new PictureComparer()).Skip(0 * 10).Take(10).ToList();

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

饮湿 2024-12-21 21:10:32

删除对 ToList 的第一次调用并使用 lambda 表达式而不是定义比较器:

var result = db.Pictures
    .Include(q => q.Tags)
    .Include(q => q.User)
    .OrderByDescending(q => 
         q.PositiveVotes + q.NegativeVotes == 0
             ? -1
             : q.PositiveVotes / (double)(q.PositiveVotes + q.NegativeVotes))
    .Skip(n * 10)
    .Take(10)
    .ToList();

Remove the first call to ToList and use a lambda expression instead of defining a comparer:

var result = db.Pictures
    .Include(q => q.Tags)
    .Include(q => q.User)
    .OrderByDescending(q => 
         q.PositiveVotes + q.NegativeVotes == 0
             ? -1
             : q.PositiveVotes / (double)(q.PositiveVotes + q.NegativeVotes))
    .Skip(n * 10)
    .Take(10)
    .ToList();
我的痛♀有谁懂 2024-12-21 21:10:32

比较器代码中的计算是独立的(即比较仅取决于订购一个可以在不参考您要比较的项目的情况下计算的值)。因此,您应该首先计算您的正百分比数,然后在比较器中使用计算出的值。

如果可能的话,这当然应该在数据库中完成(即,如果您有权对数据库进行更改)。数据库适合这种计算,您可能可以即时进行计算,而无需缓存计算值,我的意思是有一个视图可以为您计算出百分比,而不是每次出现时都预先计算和存储该值投赞成票或反对票。这样就无需下载所有照片进行比较,因为您只需按正百分比进行排序即可。下面是一些可以完成这项工作的示例 sql(请注意,这只是一个示例...您可能希望将投票存储为更有效的方式)。投票表包含对特定图片的所有投票以及投票者的列表。

declare @votes table(
pictureId int,
voterId int,
vote int)

insert into @votes select 1,1,1
insert into @votes select 1,2,-1
insert into @votes select 1,3,1
insert into @votes select 1,4,1
insert into @votes select 2,1,-1
insert into @votes select 2,2,-1
insert into @votes select 2,3,1
insert into @votes select 2,4,1

declare @votesView table(
pictureId int,
positiveVotes int,
NegativeVotes int)

insert into @votesView
select pictureId, sum(case when vote > 0 then 1 else 0 end) as PositiveVotes, 
SUM(case when vote < 0 then 1 else 0 end) as NegativeVotes from @votes group by pictureId

select pictureId, convert(decimal(6,2),positiveVotes) / convert(decimal(6,2), (positiveVotes + negativeVotes)) as rating from @votesView

The calculations in your comparer code are independent (i.e. the comparison just depends on ordering a value that can be calculated without reference to the item you are comparing to). Therefore you should calculate your positive percentage number first and just use the calculated value in your comparer.

This should certainly be done in the database if possible (i.e. if you have access to make changes to the database). Databases are suited to this kind of calculation and you could probably do it on the fly without having to cache the calculated values, by which I mean have a view that works out the percentage for you rather than precalculating and storing the value everytime there is a positive or negative vote. This will obviate the need to download all the photos to compare, as you can just order by the positive percentage. Below is some sample sql that will do the job (note it is only a sample...you might want to store the vote as a bit or something more efficient). The votes table contains a list of all votes for a particular picture and who voted for it.

declare @votes table(
pictureId int,
voterId int,
vote int)

insert into @votes select 1,1,1
insert into @votes select 1,2,-1
insert into @votes select 1,3,1
insert into @votes select 1,4,1
insert into @votes select 2,1,-1
insert into @votes select 2,2,-1
insert into @votes select 2,3,1
insert into @votes select 2,4,1

declare @votesView table(
pictureId int,
positiveVotes int,
NegativeVotes int)

insert into @votesView
select pictureId, sum(case when vote > 0 then 1 else 0 end) as PositiveVotes, 
SUM(case when vote < 0 then 1 else 0 end) as NegativeVotes from @votes group by pictureId

select pictureId, convert(decimal(6,2),positiveVotes) / convert(decimal(6,2), (positiveVotes + negativeVotes)) as rating from @votesView
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文