Отображение случайных строк без повторения - PullRequest
0 голосов
/ 04 февраля 2019

Мои проблемы:

  1. Как отображать случайные объявления, чтобы одно и то же объявление больше не появлялось.
  2. Как придать значение объявлению с более высокой стоимостью кредита.

Таблица БД Sql-сервера

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 объявлений одновременно (придавая значение кредитам, имеющим более высокую стоимость).

Мой подход

  1. В настоящее время я выбираю10 случайных объявлений из таблицы объявлений и их отображение.
  2. Также добавлен флаг IsAdDisplayed (логический) в таблицу объявлений, чтобы одно и то же случайное объявление не повторялось (пока не будут показаны все объявления)
  3. когда я закончу показывать все объявления, я снова обновляю IsAdDisplayed на false.

LINQ

var result = (from u in idb.ads
      select u).OrderBy(x => Guid.NewGuid()).Take(10);

Но это не займетболее высокие кредиты к рассмотрению.

Это правильный подход?Как отображать случайные объявления (с учетом кредитов) и чтобы эти объявления не повторялись?

Ответы [ 3 ]

0 голосов
/ 04 февраля 2019

Как показывать случайные объявления (с учетом кредитов) и чтобы эти объявления не повторялись?

Если вы хотите отдать приоритет кредитам, вы можете попробовать написатьзапросить что-то вроде следующего (вам может потребоваться преобразовать его в LINQ).

Здесь запись, имеющая больше кредитов, получит больший приоритет.Как credit > 80 получит наивысший приоритет, а credit < 40 получит наименьший приоритет.

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 голосов
/ 04 февраля 2019

Вы писали:

, придавая значение кредитам с более высокой стоимостью

Означает ли это, что, если у вас есть не показанные объявления с кредитом 40, вывообще не хотите показывать рекламу с кредитом 10?Или вы имеете в виду, что вы хотите, чтобы объявления с более высокими кредитами имели более высокий шанс показа.И если так: если кредиты в 4 раза выше, должен ли шанс быть показан в четыре раза больше?

Давайте предположим, что вы не хотите показывать объявления с более низкими кредитами, пока вы не показывалиобъявления с более высоким кредитом.

int nrOfAdsToSelect = ...;
var selectedAds = dbContext.Adds
    .Where(ad => !ad.IsSelected)
    .OrderyDescending(ad => ad.Credit)
    .Take(nrOfAddsToSelect);

Однако, если вы хотите, чтобы все объявления имели возможность показа, только объявления с более высоким кредитом имеют более высокий шанс, вам следует подумать о том, насколько выше этот шанс.

Проще всего было бы перевести кредит в диапазон целых чисел, указывающих, когда нужно выбрать объявление:

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, в 10 раз выше, чем вероятность выбора идентификатора 01.

Итак, вам нужна функция для создания целочисленного диапазона из Credit и StartNumber.Это может быть так же просто, как указано выше, это может быть любой другой алгоритм, в зависимости от того, насколько вы оцениваете шансы объявлений с более высоким кредитом.

Вы можете использовать свою функцию кредитования в диапазон, чтобы преобразовать последовательность не-displayed Добавляет в последовательность целых чисел.

В качестве функций расширения:

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;
        }
    }
}

Использование:

List<Ad> ads = ...
var range = ads.ToRange().ToList();
int selectedIndex = rnd.Next(range.Count);
var firstSelectedAdd = ads[selectedIndex];

Проблема в том, что, как только вы выбралиВаше первое объявление, шансы вашего второго объявления должны измениться.Вам нужно будет создать новый диапазон:

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 голосов
/ 04 февраля 2019

Попробуйте следующее:

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();

        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...