Как получить массив, в котором последний элемент не является ни предыдущим элементом, ни первым элементом?


У меня есть ползунок с циклом (за последним элементом следует первый элемент), и я хочу установить другой цвет (на основе диапазона из 3 цветов).

Таким образом, существует 2 условия: предыдущий цвет и следующий цвет не должны быть одинаковыми, И количество слайдов (элементов в массиве) может отличаться.

Хороший пример:

Array
(
    [0] => yellow
    [1] => blue
    [2] => red
    [3] => yellow
    [4] => red
)

Плохой пример (потому что элементы 0 и 4 одного цвета):

Array
(
    [0] => yellow
    [1] => blue
    [2] => yellow
    [3] => red
    [4] => yellow
)

Еще один плохой пример с большим количеством элементов (потому что элементы 2 и 3 одинаковы цвет):

Array
(
    [0] => yellow
    [1] => blue
    [2] => red
    [3] => red
    [4] => blue
    [5] => yellow
    [6] => blue
)

Это то, что я пытаюсь, но я не думаю, что это хороший способ:

$i = 0;
$bgcolors = array();
foreach($slides as $slide) {
    switch ($i % 3) {
        case 0:
            $bgcolors[] = 'yellow';
            break;
        case 1:
            $bgcolors[] = 'blue';
            break;
        case 2:
            $bgcolors[] = 'red';
            break;
    }

    if ((count($slides) - $i) % 3 == 0) $i = 0;

    $i++;
}
 3
Author: Dacobah, 2016-09-16

6 answers

Но я не думаю, что это хороший способ

Это относительно элегантный и эффективный способ убедиться, что у вас нет последовательных совпадающих цветов за один проход по результатам. Но это могло бы быть более элегантно, используя метод, предложенный Йеруном.

Однако это не решает проблему, когда список обтекается. Очевидно, что при неизвестном количестве слайдов (M) существует вероятность 1 из N (где N - количество цветов), что 1-й слайд будет выделен тем же цветом, что и предыдущий. Но это просто понять, когда это так:

M % N = 1

Таким образом, пока M%N не является таковым, это проблема, о которой вам не нужно беспокоиться. Когда M%N равно 1, вам нужно только беспокоиться об изменении цвета либо первого или последнего слайда. В качестве аргумента мы изменим цвет последнего.

Так что остается только решить проблему, какой цвет выбрать.

В отсутствие изменений последний слайд будет будьте того же цвета, что и первый, и мы не можем изменить его на цвет в начале цикла, так как это сделает его таким же, как на предпоследнем слайде.

Решение Йоруна довольно запутанное - найдите цвет, который не использовался на предыдущих или более поздних слайдах, и примените его. Он использует больше кода, чем необходимо. Вы просто выбираете второй цвет в списке.

Однако йерун ошибается, говоря, что проблему можно решить с помощью 2 цветов (или меньше!). Никакое количество кода не поможет, если только 2 цвета и нечетное количество слайдов больше 1.

Следовательно:

  $colors = ['yellow', 'blue', 'red'];
  if (count($slides)>count($colors) && 3>count($colors)) {
      trigger_error("unsolvable");
  }
  $i = 0;
  $bgcolors = array();
  foreach($slides as $slide) {
     $bgcolors[] = $colors[$i % count($colours)];
     $i++;
  }
  if (1 < count($slides) && 1 == count($slides) % count($colors)) {
     $bgcolors[count($slides)-1]=$colors[1];
  }
 1
Author: symcbean, 2016-09-16 16:19:57

Вам следует начать с размещения ваших цветов в массиве.

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

$colors = ['yellow', 'blue', 'red'];
$i = 0;
$bgcolors = array();
foreach($slides as $slide) {
    $bgcolors[] = $colors[$i % 3];

    $i++;

    if ($slide == end($slides) {
        $j = $i;
        while ($bgcolors[$i - 1] === $colors[$j % 3] || $bgcolors[0] === $colors[$j % 3]) {
            $j++;
        }
        $bgcolors[] = $colors[$j % 3];
    }
}

Обратите внимание, что вам нужно добавить условия, если ваш массив цветов или слайдеров может содержать 2 элемента или меньше...

 1
Author: jeroen, 2016-09-16 10:52:55

Предполагая, что цвета могут быть случайными (за исключением упомянутых ограничений, конечно):

$slides = array('slide1', 'slide2', 'slide3', 'slide4', 'slide5');
$colors = array('red', 'blue', 'yellow');
$bg_colors = array();

foreach ($slides as $key=>$value) {
    if ($key == 0) { // First slide
        $bg_colors[] = $colors[mt_rand(0, 2)]; // Get random color
    } else { // Other slides
        $usable_colors = $colors; // Duplicate colors array
        $usable_colors = array_values(array_diff($usable_colors, array($bg_colors[$key-1]))); // Remove last used color and reset keys
        if ($key == count($slides) -1) { // Last slide
            $usable_colors = array_values(array_diff($usable_colors, array($bg_colors[0]))); // Remove first used color and reset keys
        }
        $bg_colors[] = $usable_colors[mt_rand(0, count($usable_colors)-1)]; // Get random color
    }
}
 0
Author: roberto06, 2016-09-16 10:20:11

Простой способ сделать это - запросить все возможные цвета, отличные от последнего и первого в слайдере, а затем выбрать один наугад.

function getColorsForElements( $numbersOfElements ) {

$colors_array   = array('red', 'blue', 'yellow');
$bg_colors  = array();

for ($i = 0; $i < $numbersOfElements; $i++) {
    if  ($i == $numbersOfElements - 1 )
        $first_color    = reset($bg_colors);
    else
        $first_color = false;

    $last_color     = end($bg_colors);

    $possible_colors = array_diff($colors_array, array($first_color, $last_color) );

    $index = array_rand($possible_colors, 1);
    array_push($bg_colors, $possible_colors[$index] );
}

return $bg_colors;
}

Примером использования является getColorsForElements( 5 ), который дает в результате:

Array
(
    [0] => yellow
    [1] => blue
    [2] => red
    [3] => blue
    [4] => red
)
 0
Author: Sylter, 2016-09-16 12:18:28
$colors = ['yellow', 'blue', 'red'];
$bgcolors = array($colors[2]);
for ($i = 1; $i < count($slides); ++$i) {
    $bgcolors[] = $colors[$i%2];
}

Это соответствует вашим двум условиям. Но теперь вы, вероятно, расскажете мне о третьем, потому что это не может быть так просто:-)

 0
Author: Paul Spiegel, 2016-09-16 14:29:42

Насколько я понимаю ваш вопрос, вот решение

$i = 0;
$bgcolors = array();
foreach($slides as $slide) {
if ($i > 2) $i = 0;
switch ($i) {
    case 0:
        $bgcolors[] = 'yellow';
        break;
    case 1:
        $bgcolors[] = 'blue';
        break;
    case 2:
        $bgcolors[] = 'red';
        break;
}

$i++;
}
 -1
Author: Imran Hussain, 2016-09-16 10:22:51