如何获取最后一个元素既不是前一项也不是第一个元素的数组?

How to get an array where the last element is neither the previous item or the first element?

我有一个带有循环的滑块(最后一个元素后跟第一个元素)并且想要设置不同的颜色(基于 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++;
}

假设颜色可以是随机的(当然除了提到的限制):

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

您应该从将颜色放入数组开始。

然后,在数组的末尾,您需要添加一些逻辑来确保既不使用前一个颜色也不使用第一个颜色:

$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 个或更少的元素,则需要添加条件...

根据我的理解,这是解决方案

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

一个简洁的方法是询问滑块中与最后一个和第一个不同的所有可能颜色,然后随机选择一个。

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
)

but I don't think this is the good way

这是一种相对优雅且高效的方法,可确保您在单次遍历结果时不会出现连续的匹配颜色。但是使用jeroen提出的方法可能更优雅

但是它没有解决列表回绕的问题。显然,对于未知数量的幻灯片 (M),有 N 分之一的机会(其中 N 是颜色的数量)第一张幻灯片将被分配与最后一张相同的颜色。但是遇到这种情况很容易解决:

M % N = 1

因此,只要 M%N 不是一个,您就不必担心。当 M%N 为 1 时,您只需要担心更改 第一张或最后一张幻灯片的颜色。为了争论,我们把最后一个的颜色改一下。

这样就剩下选择哪种颜色的问题了。

在没有更改的情况下,最后一张幻灯片的颜色将与第一张相同,我们无法将其更改为循环中较早的颜色,因为那样会使它与倒数第二张幻灯片相同。

Joeroen 的解决方案相当混乱 - 搜索之前或之后的幻灯片中未使用的颜色并应用它。它使用了比必要更多的代码。您只需选择列表中的第二种颜色。

然而,jeroen 说问题可以用 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];
  }
$colors = ['yellow', 'blue', 'red'];
$bgcolors = array($colors[2]);
for ($i = 1; $i < count($slides); ++$i) {
    $bgcolors[] = $colors[$i%2];
}

这符合你的两个条件。但现在你可能会告诉我第三个,因为它没那么容易:-)