改善糟糕的阵列逻辑

时间:2017-01-22 17:09:58

标签: php arrays refactoring

我正在轮盘赌模拟器上工作以获得乐趣。我按照它们出现在方向盘上的顺序在车轮上有一组数字;

public static $number = [
    0 => ['colour' => 'green', 'value' => 0],
    1 => ['colour' => 'red', 'value' => 32],
    2 => ['colour' => 'black', 'value' => 15],
    3 => ['colour' => 'red', 'value' => 19],
    4 => ['colour' => 'black', 'value' => 4],
    5 => ['colour' => 'red', 'value' => 21],
    6 => ['colour' => 'black', 'value' => 2],
    7 => ['colour' => 'red', 'value' => 25],
    8 => ['colour' => 'black', 'value' => 17],
    9 => ['colour' => 'red', 'value' => 34],
    10 => ['colour' => 'black', 'value' => 6],

最多36岁。我想做一个"和邻居"将拉出邻居"的功能给定数字的任一侧。例如。如果" 2"选中然后返回将是上述数组的子部分;

[
    4 => ['colour' => 'black', 'value' => 4],
    5 => ['colour' => 'red', 'value' => 21],
    6 => ['colour' => 'black', 'value' => 2],
    7 => ['colour' => 'red', 'value' => 25],
    8 => ['colour' => 'black', 'value' => 17],
];

所以我的功能如下;

public static function getNeighbours($number)
{
    $key = array_search($number, array_column(self::$number, 'value'));

    $output = [];

    if ($key == 0) {
        $output[] = self::$number[35];
        $output[] = self::$number[36];
        $output[] = self::$number[0];
        $output[] = self::$number[1];
        $output[] = self::$number[2];
    } else if ($key == 1) {
        $output[] = self::$number[36];
        $output[] = self::$number[0];
        $output[] = self::$number[1];
        $output[] = self::$number[2];
        $output[] = self::$number[3];
    } else if ($key == 35) {
        $output[] = self::$number[33];
        $output[] = self::$number[34];
        $output[] = self::$number[35];
        $output[] = self::$number[36];
        $output[] = self::$number[0];
    } else if ($key == 36) {
        $output[] = self::$number[34];
        $output[] = self::$number[35];
        $output[] = self::$number[36];
        $output[] = self::$number[0];
        $output[] = self::$number[1];
    } else {

        if (isset(self::$number[$key - 2])) {
            $output[] = self::$number[$key - 2];
        }

        if (isset(self::$number[$key - 1])) {
            $output[] = self::$number[$key - 1];
        }

        $output[] = self::$number[$key];

        if (isset(self::$number[$key + 1])) {
            $output[] = self::$number[$key + 1];
        }

        if (isset(self::$number[$key + 2])) {
            $output[] = self::$number[$key + 2];
        }
    }

    return $output;
}

工作正常。甚至可以说明是选择了低数字还是高数字(如果您知道术语"以及邻居"可能会有帮助。

但它不是很优雅。如何将此功能设为批次更小?

5 个答案:

答案 0 :(得分:1)

这里有一些优雅的数学可以帮到你,37是你在数组中拥有的元素总数。例如,您可以将其替换为count($array)

function getNeighbourKeys($i) 
{
    return  [
        (($i - 2 + 37) % 37),     // index of the one before previous
        (($i - 1 + 37) % 37),     // index of a previous element
        $i,                       // index of your element
        ($i + 1) % 37,            // index of a next element
        ($i + 2) % 37             // index of the one after next
    ];
}

之后:

$output = [];
$keys = getNeighbourKeys($i);
foreach ($keys as $k) {
    if (isset(self::$number[$k])) {
        $output[] = self::$number[$k];
    }
}

答案 1 :(得分:0)

如果你谷歌“轮盘赌数字颜色”谷歌将说“轮盘赌的口袋编号从0到36.数字范围从1到10和19到28,奇数是红色,甚至是黑色。范围从11到18和29到36,奇数是黑色甚至是红色。有一个绿色口袋编号为0(零)“这很容易实现像这样的功能:

function number($i) {
      if ($i == 0) { //There's a variant with "00" I think
         return [ "color" => "green", "number" => $i ];
      } elseif (($i >= 1 && $i <= 10) || ($i >= 19 && $i <= 28)) {
         return [ "color" => ($i%2==0?"red":"black"), "number" => $i ];
      } else {
         return [ "color" => ($i%2==0?"black":"red"), "number" => $i ];
      } 
}

现在,邻居是数字上方和下方2的滑动窗口,因此它们是:

  public static function getNeighbours($number) {
        $output = [];
        for ($i = ($number-2)%37;$i <= ($number+2)%37;$i = ($i+1)%37) {
            $output[] = self::number($i);
        }
        return $output;

  }

这是一般的想法。

答案 2 :(得分:0)

重构代码的算法如下:

  • self::$number数组中获取超集范围的键,如此

    $totalCount = count(self::$number);
    $supersetRange = range(0, $totalCount - 1);
    
  • 根据传递给函数的值self::$number$number数组中搜索密钥,如下所示:

    $key = array_search($number, array_column(self::$number, 'value'));
    
  • 根据上面派生的密钥从self::$number数组中获取子集范围的键,如下所示:

    $subsetRange = range($key - 2, $key + 2);
    
  • 现在使用以下foreach循环调整此子集键范围,

    foreach($subsetRange as $p){
        if($p < 0){
            array_shift($subsetRange);
            if(in_array($subsetRange[count($subsetRange) - 1] + 1, $supersetRange)){
                $subsetRange[] = $subsetRange[count($subsetRange) - 1] + 1;
            }
        }elseif($p > $totalCount - 1){
            array_pop($subsetRange);
            if(in_array($subsetRange[0] - 1, $supersetRange)){
                array_unshift($subsetRange, $subsetRange[0] - 1);
            }
        }
    }
    
  • 现在根据上面的子集键范围将self::$number数组的相应元素推送到$output数组,如下所示:

    $output = array();
    foreach($subsetRange as $key){
        $output[] = self::$number[$key];
    }
    
  • 最后从静态方法

    返回此$output数组
    return $output;
    

所以 getNeighbours()方法的完整代码如下:

public static function getNeighbours($number){
    $totalCount = count(self::$number);
    $supersetRange = range(0, $totalCount - 1);
    $key = array_search($number, array_column(self::$number, 'value'));
    $subsetRange = range($key - 2, $key + 2);
    foreach($subsetRange as $p){
        if($p < 0){
            array_shift($subsetRange);
            if(in_array($subsetRange[count($subsetRange) - 1] + 1, $supersetRange)){
                $subsetRange[] = $subsetRange[count($subsetRange) - 1] + 1;
            }
        }elseif($p > $totalCount - 1){
            array_pop($subsetRange);
            if(in_array($subsetRange[0] - 1, $supersetRange)){
                array_unshift($subsetRange, $subsetRange[0] - 1);
            }
        }
    }

    $output = array();
    foreach($subsetRange as $key){
        $output[] = self::$number[$key];
    }
    return $output;
}

答案 3 :(得分:0)

一个简单,循序渐进,富有表现力的方法;

public static function getNeighbours($number)
{
    // get the key
    $key = array_search($number, array_column(self::$number, 'value'));

    // determine range of keys
    $range = range($key - 2, $key + 2);
    $output = [];

    foreach ($range as $k => $item) {
        // keep the values inside the range
        if ($item < 0) {
            $item = 37 + $item;
        } else if ($item > 36) {
            $item = $item - 37;
        }
        // add section to the output
        $output[] = self::$number[$item];
    }

    return $output;
}

答案 4 :(得分:0)

在算术 模数 运算符中使用初始数组的项目数作为除数

public static function getNeighbours($value) {
    $key = array_search($value, array_column(self::$number, 'value'));
    $divisor = count(self::$number);
    $neighbours = [];

    foreach ([-2, -1, 0, 1, 2] as $step) {
        $divident = (($d = ($key + $step)) < 0)? $divisor + $d : $d;
        $neighbours[] = self::$number[$divident % $divisor];
    }

    return $neighbours;    
}

http://php.net/manual/en/language.operators.arithmetic.php