【问题标题】:Adding unknown amount of objects to Array via function通过函数将未知数量的对象添加到数组
【发布时间】:2020-10-24 17:48:37
【问题描述】:

所以,首先。我是一名 C# 程序员,所以我的 PHP 代码可能会受到你用 C# 编写的方式的强烈影响。无论如何,我正在尝试解决一个问题,即我有一个带有两个轴 x 和 y 的二维网格。用户输入,程序会告诉你你的新位置。

例如,如果用户输入是“>^”,则位置将为 1,1。
我还希望程序做的是告诉您您重访的第一个位置。所以,如果你从 0,0 -> 0,1 -> 0,0 -> 1,0 -> 1,1 开始。然后您重新访问的第一个位置是 0,0。 我的问题是我试图将我的 int 发送到一个函数,然后将它添加到一个数组中,如果数组包含该对象,则搜索该数组。但似乎数组只添加了一个值(?)

declare(strict_types=1);
<?php

$NewInput = ">>^^<>>";
$arr = str_split($NewInput, 1);
$x = 0;
$y = 0;
Directions($x, $y, $arr);
function Directions (int $x, int $y, $arr)
{
    foreach ($arr as $item)
    {
        if ($item == '^')
        {
            $y += 1;
        }
        elseif ($item == 'v')
        {
            $y -= 1;
        }
        elseif ($item == '>')
        {
            $x += 1;
        }
        elseif ($item == '<')
        {
            $x -= 1;
        }
        Previous($x,$y);
    }
}
function Previous (string $x, string $y)
{
    $Location = $x . '.' . $y;
    echo "<br>";
    $NewArray = array();
    $NewArray[] = $Location;
    $ReVisited = "";
    if ($ReVisited == "")
    {
       if (array_search($Location, $NewArray))
        {
            $ReVisited = $Location;
            echo $ReVisited;
        }
    }
    echo $Location;
}
?>

我做错了什么? 另外,如果您看到可以改进的代码的整体内容,请告诉我。 感谢任何提示或答案!

【问题讨论】:

  • 能否请您提取并提供minimal reproducible example?另外,程序在什么时候没有按预期运行?而你期待什么呢?作为这里的新用户,也可以使用tour 并阅读How to Ask。作为新的 PHP 程序员,请查看 PSR 文档,尤其是有关命名和格式的编码指南。您将更轻松地与他人合作。
  • 我的错。谢天谢地,我没有因为我的坏问题而得到帮助。将来会更仔细地构建我的问题。

标签: php arrays function


【解决方案1】:

与其他答案一样:您的代码不起作用的关键原因是您每次调用函数 Previous() 时都在重新初始化 $newArray,因此数组为 null

要解决这个问题,您可以按照@Andrew 的建议使用 global

但是,您的代码似乎有点杂乱无章且过于复杂......似乎不需要两个单独的函数?整个过程实际上是一个功能。

如果你把它当作一个函数,那么你就不需要使用globals,你可以用更少的代码行来完成它!

$NewInput    = ">>^^<>>";
$arr         = str_split($NewInput, 1);
$x           = 0;
$y           = 0;

directions($x, $y, $arr);

function directions($x, $y, $arr){
    $used_points = []; // Array of points which have been passed through
    $repeats     = []; // Array of points which have been repeated
    foreach ($arr as $item) {
        switch ($item) {
            case '^':
                $y += 1;
                break;
            case 'v':
                $y -= 1;
                break;
            case '>':
                $x += 1;
                break;
            case '<':
                $x -= 1;
                break;
        }

        $current_point = "{$x}.{$y}";
        $repeat        = in_array($current_point, $used_points); // Checks if the point is repeated
        echo $current_point . (($repeat) ? " REPEAT\n" : "\n");  // Outputs current point and whether it's a repeat

        $used_points[] = $current_point; // Add current point to $used_points array
    }
}

/*  Output:
        1.0
        2.0
        2.1
        2.2
        1.2
        2.2 REPEAT
        3.2
*/

补充说明

开关

switch 语句实际上只是以更易于阅读的方式编写if...elseif 语句的另一种方式。从功能上讲,它执行相同的工作(即将给定值与另一个值进行比较)。

下面的三个代码示例显示了比较值的不同方式。第三个例子实际上就是switch 语句。

注意在switchwhile 语句中需要break 才能退出语句。如果您省略它,那么代码将继续在页面下方运行,超出您的预期。

## Example code with switch
switch ($test_case){
    case 1:
        // Do something if $test_case == 1...
        break;
    case 2:
        // Do something if $test_case == 2...
        break;
}

## Example code with if/elseif
if($test_case == 1){
    // Do something if $test_case == 1...
}
elseif($test_case == 2){
    // Do something if $test_case == 2...
}

## Example of if statements in a loop equivalent to switch
while(TRUE){
    if($test_case == 1){
        // Do something if $test_case == 1...
        break;
    }
    if($test_case == 2){
        // Do something if $test_case == 2...
        break;
    }
    break;
}

{ 花括号 } 和双引号

你可以直接在双引号内引用变量;这通常会使代码更容易阅读和更好看。示例:

echo $a . ", " . $b . ", " . $c . ", " $d;
echo "$a, $b, $c, $d";

但是,在某些情况下,执行上述操作可能会产生意想不到的结果。花括号有助于将其保持在最低限度,并且是一个很好的实践 - 它们清楚地指定了您要引用的变量。

$current_point = "$x.$y"; // is equivalent to....
$current_point = "{$x}.{$y}";

in_array($needle, $haystack)

in_array 只是一种检查数组中是否存在值的方法。如果找到该值,则该函数返回TRUE,否则返回FALSE

线...

$repeat = in_array($current_point, $used_points);

...因此将$repeat 设置为TRUEFALSE

三元运算符

三元运算符实际上是一个简写的if...else 语句。

## Example of if/else
$output = "";
if($value == TRUE){
    $output = 1;
}
else{
    $output = 2;
}

## Example with ternary operator
$output = ($value) ? 1 : 2;

在您的情况下,我们使用它来检查 $repeat 是否为 TRUE(即当前坐标存在于已访问的坐标数组中)。如果是TRUE,那么我们就输出 REPEAT\n或者\n,如果不是。

echo ($repeat) ? " REPEAT\n" : "\n";

整行……

echo $current_point . (($repeat) ? " REPEAT\n" : "\n");

...然后输出$current_point,后跟 REPEAT\n\n

【讨论】:

  • 这是一个更好、更完整的答案,代码更性感。干杯!
  • 这段代码很棒。创造奇迹!对我来说最大的问题是我很难真正理解代码中的所有内容。
  • 我已经对一些常见的麻烦点添加了进一步的解释......希望这能解决问题!
  • 哇!太棒了!非常感谢。这清除了 99% 的我不明白的东西。你是明星!
【解决方案2】:

如果我正确理解您想要的结果,我不是 100%,但以下是我看到的问题: 在 Previous 函数中不断地重新定义 $NewArray,因此每次运行它时,数组都会变为空。您必须将该变量放在函数之外,并使用global 范围引用它。我还将它重命名为 $previousLocations。这是新功能:

$previousLocations = array();
function Previous (string $x, string $y)
{
    global $previousLocations;
    $Location = $x . '.' . $y;
    echo "<br>";
    if(in_array($Location, $previousLocations)) {
      // Already visited location
      echo "Revisiting: " . $Location;
    } else {
      $previousLocations[] = $Location;
      echo $Location;
    }
}

输出: 1.0 2.0 2.1 2.2 1.2 重访:2.2 3.2

如果我误解了什么,请纠正我。

【讨论】:

  • 这是我的失误,每次都重新定义数组。您理解正确,我的错误是我解释得很糟糕。无论如何,当我尝试你的代码时,它永远不会是真的,只会是假的。因此,即使我有已经访问过的位置,它也不会写出来。
  • 这很奇怪,它似乎在这里的演示中工作:3v4l.org/rF67d(我还修复了第一次检查时未定义数组的警告)
  • 嗯,这很尴尬...我写的是 $PreviousLocation 而不是 $previousLocation。所以大写P是问题所在。我已经习惯于收到这样的简单失误的错误消息。改变了,现在它工作了!感谢您的帮助!。
猜你喜欢
  • 1970-01-01
  • 2020-04-09
  • 1970-01-01
  • 1970-01-01
  • 2022-01-14
  • 2021-01-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多