Мне пришлось написать что-то в MVC для взвешенного рекламного контроля, который бы не показывал одно и то же объявление дважды подряд, если это возможно, и в спешке у меня получился ужасный кусок кода, который мог бы послужить вам вдохновением.
Я уверен, что есть много лучших способов сделать это (и я уже знаю случаи, когда это позволяет дублировать, когда это не должно), но за короткое время, которое я потратил на это, он сделал свою работу.
public List<Ad> GetRandomWeightedAds()
{
/* Generate random order list of ads with duplicates for ViewsPerRotation */
List<Ad> returnList = GetAllAds().SelectMany(s => Enumerable.Repeat(s, s.ViewsPerRotation)).OrderBy(s => Guid.NewGuid()).ToList();
for (int i = 0; i < returnList.Count - 1; i++) /* Compare all but the last element against subsequent element */
{
if (returnList[i].Id == returnList[i + 1].Id)
{
/* If next to an identical element try and find a new spot for the subsequent element */
for (int j = 0; j < returnList.Count; j++)
{
if (returnList[j].Id != returnList[i].Id /* Don't switch identical element back into same pos*/
&& (j<i || j == 0 || j-1 == i || returnList[i].Id != returnList[j - 1].Id) /* When moving before current 'i', don't move into a place after an identical element */
&& (j<i || j == returnList.Count - 1 || j + 1 == i || returnList[i].Id != returnList[j + 1].Id)) /* When moving before current 'i', don't move into a place before an identical element */
{
returnList[i] = returnList[j];
returnList[j] = returnList[i+1]; /* returnList[i+1] == returnList[i] */
break;
}
}
}
}
return returnList;
}