Фильтруйте и сортируйте многомерный массив в переполнении стека

Я создаю галерею изображений и хочу добавить несколько рекламных баннеров в случайные моменты, чтобы продвигать определенные предложения пользователям. Учитывая, что следующий массив исходит из запроса к базе данных:

    Array
(
[0] => Array
(
[insertDate] => 2014-11-10 11:22:58
[keyword] => standard
[mediaClass] => image
[mediaURL] => http://image1.jpg
[promoURL] =>
)

[1] => Array
(
[insertDate] => 2014-11-10 11:23:08
[keyword] => promo
[mediaClass] => image
[mediaURL] => http://image2.jpg
[promoURL] => http://www.google.com
)

[2] => Array
(
[insertDate] => 2014-11-10 11:23:18
[keyword] => standard
[mediaClass] => image
[mediaURL] => http://image3.jpg
[promoURL] =>
)

[3] => Array
(
[insertDate] => 2014-11-10 11:23:28
[keyword] => standard
[mediaClass] => image
[mediaURL] => http://image4.jpg
[promoURL] =>
)

[4] => Array
(
[insertDate] => 2014-07-08 11:23:38
[keyword] => promo
[mediaClass] => image
[mediaURL] => http://image5.jpg
[promoURL] => http://www.google.com
)

[5] => Array
(
[insertDate] => 2014-07-08 11:23:48
[keyword] => standard
[mediaClass] => image
[mediaURL] => http://image6.jpg
[promoURL] =>
)
)

Я пытаюсь сделать две вещи;

1)

Убедитесь, что есть только один рекламный изображение в 5 стандарт images (в этом примере их 2, поэтому нужно будет удалить / отфильтровать их из массива с помощью ключевого слова key). Это сделано для того, чтобы пользователь не спамил слишком много рекламных баннеров.

2)

Рамдомизируйте положение любых изображений с помощью рекламный ключевое слово, но по-прежнему поддерживать порядок изображений с стандарт ключевое слово по insertDate.

Принимая во внимание, что размер этих наборов результатов всегда будет различным, каков будет наилучший способ программного достижения этого?

редактировать: я создал следующую функцию для решения первой части:

function limitMediaPromos($array, $key, $value, $limit)
{
// count the number of promo images
if($count = $this->countElementsWithValue($array, $key, $value))
{
// find the avg number of promos per media set
$avg = floor((count($array) / $count));

// remove promo element if avg is over set limit
if($avg > $limit)
{
$array = $this->removeElementWithValue($array, $key, $value);
}
}

return $array;
}

0

Решение

Для лучшей производительности сортируйте на стороне базы данных и удалите функцию mediaSort и usort ($ medias, ‘mediaSort’); ниже.

function isMedia($var)  {
return empty($var['promoURL']);
}

function isPromo($var)
{
return !empty($var['promoURL']);
}

function mediaSort($mediaOne, $mediaTwo)
{
return (strtotime($mediaOne['insertDate']) <= strtotime($mediaTwo['insertDate']));
}

function getImages($input)
{
// Get the promos. O(n).
$promos = array_filter($input, "isPromo");
// randomize them. O(n).
shuffle($promos);

// Get the medias. O(n)
$medias = array_filter($input, "isMedia");
// Sort them (ideally sort it on the database side and skip this step). O(n log n)
usort($medias, 'mediaSort');

$promoOdds = 1/5;
$promoGap = 5;
$returnIndex = 0;

$return = array();
foreach ($medias as $media) {
if (is_null($lastPromoIndex)
|| $returnIndex > $lastPromoIndex + $promoGap
) {
if (rand(1,1/$promoOdds) == 1) {
$return[] = array_pop($promos);
$lastPromoIndex = $returnIndex;
}
}
$return[] = $media;
$returnIndex++;
}

if (is_null($lastPromoIndex)
|| $returnIndex > $lastPromoIndex + $promoGap
) {
$return[] = array_pop($promos);
}

return $return;
}

print_r(getImages($input));
0

Другие решения

Других решений пока нет …