【问题标题】:How to get an array where the last element is neither the previous item or the first element?如何获取最后一个元素既不是前一项也不是第一个元素的数组?
【发布时间】:2016-09-16 10:08:31
【问题描述】:

我有一个带循环的滑块(最后一个元素后跟第一个元素),并且想要设置不同的颜色(基于 3 种颜色的范围)。

所以有两个条件:上一个颜色和下一个颜色不能相同,并且幻灯片的数量(数组中的元素)可能会有所不同。

好例子:

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

【问题讨论】:

  • 对于第一个(好)示例,它应该是蓝色的,对吗?或者你需要不同两种颜色之间的所有颜色?
  • @HareshVidja 是的,没错。由于上一个颜色是红色,下一个颜色是黄色,因此在这种情况下,蓝色是唯一的选择。
  • 您需要数组或多种颜色,而不仅仅是满足您条件的第一种颜色?
  • 不清楚您要做什么,但是您不能将元素与下一个元素进行比较,看看它们是否相同吗? bgcolors[i] != bgcolors[(i+1)%bgcolors.length]
  • 为什么?这是一个“为我做作业”的问题吗?

标签: php modulo


【解决方案1】:

但我认为这不是好方法

这是一种相对优雅且有效的方法,可确保您在一次通过结果时没有连续匹配的颜色。但是使用 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];
  }

【讨论】:

  • 最后一部分不太好理解。但似乎是正确的方法。
  • 我绝对不是说这在所有情况下都可以解决;只是需要额外的检查来避免陷入永无止境的循环。但是,是的,您可以使用简单的数学更优雅地解决这个问题:-)
【解决方案2】:

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

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

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

【讨论】:

    【解决方案3】:

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

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

    【讨论】:

      【解决方案4】:

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

      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
      )
      

      【讨论】:

      • 不是一个干净的解决方案 - 一个蛮力解决方案
      • @symcbean 为什么会这样?
      【解决方案5】:
      $colors = ['yellow', 'blue', 'red'];
      $bgcolors = array($colors[2]);
      for ($i = 1; $i < count($slides); ++$i) {
          $bgcolors[] = $colors[$i%2];
      }
      

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

      【讨论】:

        【解决方案6】:

        我理解你的问题,这里是解决方案

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-04-20
          • 2019-04-08
          • 2023-04-08
          • 2012-04-21
          • 2013-12-01
          • 2021-09-10
          • 2019-10-19
          • 2011-01-12
          相关资源
          最近更新 更多