首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >不重复地显示随机行

不重复地显示随机行
EN

Stack Overflow用户
提问于 2019-02-04 10:29:34
回答 3查看 95关注 0票数 0

我的问题是:

  1. 如何显示随机广告,所以相同的广告不会再次出现。
  2. 如何重视信用价值较高的广告。

Sql Server DB表

代码语言:javascript
代码运行次数:0
运行
复制
AdId AdName AdUrl     Credits
 1    Ad1    abc.com   10
 2    Ad2    def.com   40
 3    Ad3    fgi.com   30
 4    Ad4    xyz.com   10

以上广告表可能包含1000条记录。我想一次展示10个广告(通过重视具有更高价值的学分)。

My Approach

  1. 我目前正在做的是从ads表中选择10个随机广告并显示它们。
  2. 还在ads表中添加了一个标志IsAdDisplayed (布尔值),以便相同的随机广告不会重复(直到它显示所有的广告)。
  3. 当我看完所有的广告后,我再次将IsAdDisplayed更新为false。

LINQ

代码语言:javascript
代码运行次数:0
运行
复制
var result = (from u in idb.ads
      select u).OrderBy(x => Guid.NewGuid()).Take(10);

但这不会考虑到更高的信用额度。

这是正确的做法吗?如何显示随机广告(考虑学分)和相同的广告不会重复显示?

EN

回答 3

Stack Overflow用户

发布于 2019-02-04 10:43:44

尝试以下几个方面:

代码语言:javascript
代码运行次数:0
运行
复制
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;

namespace ConsoleApplication100
{
    class Program
    {
        static void Main(string[] args)
        {
            DataTable dt = new DataTable();
            dt.Columns.Add("AdId", typeof(int));
            dt.Columns.Add("AdName", typeof(string));
            dt.Columns.Add("AdUrl", typeof(string));
            dt.Columns.Add("Credits", typeof (int));
            dt.Rows.Add(new object[] {1, "Ad1", "abc.com", 10});
            dt.Rows.Add(new object[] {2, "Ad2", "def.com", 40});
            dt.Rows.Add(new object[] {3, "Ad3", "fgi.com", 30});
            dt.Rows.Add(new object[] {4, "Ad4", "xyz.com", 40});

            Random rand = new Random();
            List<DataRow> randomRows = dt.AsEnumerable().Select(x => new { row = x, rand = rand.Next() }).OrderBy(x => x.rand).Select(x => x.row).ToList();
            DataTable dt2 = randomRows.CopyToDataTable();

        }
    }
}
票数 0
EN

Stack Overflow用户

发布于 2019-02-04 10:50:52

如何显示随机广告(考虑学分)和相同的广告不会重复显示?

如果您想要优先考虑学分,可以尝试编写类似以下内容的查询(可能需要将其转换为LINQ)。

在这里,有更多的信用记录将获得更多的优先权。与credit > 80一样,credit < 40将获得最高优先级,而credit < 40将获得最少的优先级。

代码语言:javascript
代码运行次数:0
运行
复制
SELECT TOP 10 * 
FROM   (SELECT * 
        FROM   (SELECT TOP 80 * 
                FROM   [table] 
                WHERE  credit > 80 
                ORDER  BY Newid())A 
        UNION ALL 
        SELECT * 
        FROM   (SELECT TOP 60 * 
                FROM   [table] 
                WHERE  credit <= 80 
                       AND credit > 60 
                ORDER  BY Newid())B 
        UNION ALL 
        SELECT * 
        FROM   (SELECT TOP 40 * 
                FROM   [table] 
                WHERE  credit <= 60 
                       AND credit > 40 
                ORDER  BY Newid())C 
        UNION ALL 
        SELECT * 
        FROM   (SELECT TOP 20 * 
                FROM   [table] 
                WHERE  credit <= 40 
                ORDER  BY Newid())D) T 
ORDER  BY Newid() 
票数 0
EN

Stack Overflow用户

发布于 2019-02-04 13:33:39

你写道:

重视有更高价值的信用

这是否意味着,只要你有信用额为40的未显示广告,你就根本不想显示带有信用10的广告?或者你的意思是说,你想给更高学分的广告更多的机会被展示。如果是这样的话:如果学分高出4倍,那么被展示的机会应该大4倍吗?

让我们假设你不想显示低学分的广告,只要你有高学分的未显示广告。

代码语言:javascript
代码运行次数:0
运行
复制
int nrOfAdsToSelect = ...;
var selectedAds = dbContext.Adds
    .Where(ad => !ad.IsSelected)
    .OrderyDescending(ad => ad.Credit)
    .Take(nrOfAddsToSelect);

然而,如果你想给所有的广告一个展示的机会,只有有更高学分的广告才有更高的机会,你应该考虑有多高的机会。

最简单的方法是将信用转换成一系列整数,指示何时选择广告:

代码语言:javascript
代码运行次数:0
运行
复制
Id Credit  => Range
00    01      00
01    01      01
02    02      02, 03                                    // credit 2: 2 numbers
03    03      04, 05, 06                                // credit 3: 3 numbers
04    10      07, 08, 09, 10, 11, 12, 13, 14, 15, 16    // 10 numbers

选取范围为00,16的随机数。选择Id 04的概率比选择Id 01的概率高10倍。

因此,您需要一个函数来从Creditand一个StartNumber创建一个整数范围。这可以像上面一样简单,也可以是任何其他算法,这取决于你对获得更高学分的广告的几率有多高。

您可以使用您的信用范围函数来转换不显示的添加到整数序列的序列。

作为推广职能:

代码语言:javascript
代码运行次数:0
运行
复制
static IEnumerable<int> ToRange(this int credit, int startNumber)
{
     // example: Credit 40 is 40 times more chance than credit 1.
     // so range length is equal to credit
     return Enumerable.Range(startNumber, credit);
}

static IEnumerable<int> ToRange(this IEnumerable<Ad> adds)
{
    int startNumber = 0;
    foreach (Ad add in adds)
    {
        // only use ads that are not displayed yet to select a new Ad.
        if (!ad.IsDisplayed)
        {
             var range = add.Credit.ToRange();
             foreach (var value in range) yield return value;
        }
    }
}

用法:

代码语言:javascript
代码运行次数:0
运行
复制
List<Ad> ads = ...
var range = ads.ToRange().ToList();
int selectedIndex = rnd.Next(range.Count);
var firstSelectedAdd = ads[selectedIndex];

问题是,一旦你选择了第一个广告,你的第二个广告的机会就会改变。您需要创建一个新的范围:

代码语言:javascript
代码运行次数:0
运行
复制
static Ad Select(this IReadOnlyList<Ad> ads)
{
    var range = ads.ToRange().ToList();
    int selectedIndex = rnd.Next(range.Count);
    return ads[selectedIndex];
}

static IEnumerable<Ad> SelectAds(this IEnumerable<Ad> ads, int selectCount)
{
    for (int i=0; i<selectCount; ++i)
    {
        var selectedAd = ads.Select();
        yield return selectedAd;
        selectedAd.IsDisplayed = true; // to make sure it is not selected again
    }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54514228

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档