Adding unknown amount of objects to Array via function

Tags: , ,



So, first off. I’m a C# programmer, so my PHP code is probably strongly influenced by how you would write in C#. Anyway, I’m trying to solve a problem where I’ve got a two-dimensional grid with two axis, x and y. The user gives input, and the program will tell you your new location.

For example, if user input was ‘ >^ ‘ the location would be 1,1.
What I also want the program to do, is to tell you the first location that you revisit. So, if you go from 0,0 -> 0,1 -> 0,0 -> 1,0 -> 1,1. Then the first location you revisited was 0,0. My problem is that I’m trying to send my int to a function and then adding it to an array, and searching the array if the array contains the object. But it seems like the array is only adding one value (?)

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

What am I doing wrong? And also if you see something overall with the code that could be improved please let me know. Grateful for any tips or answers!

Answer

As with the other answer: The key reason your code isn’t working is because you are re-initialising $newArray every time you call the function Previous() and hence the array is null.

To get around this you could use global as @Andrew suggested.

However, your code seems a little unorganised and overly complicated… There doesn’t seem to be any need for two separate functions? The whole process is effectively one function.

If you treat it as one function then you have no need of using globals and you can do it in far fewer lines of code!

$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) ? " REPEATn" : "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
*/

Additional Explanation

SWITCH

The switch statement is effectively just another way of writing your if...elseif statements in a way which is easier to read. Functionally it does the same job (i.e. comparing a given value against another).

The three code examples below show different ways of comparing the values. The third example is effectively what a switch statement is.

N.B. break is required in the switch and while statements to exit the statement. If you omit it then the code continues to run further down the page than you may have intended.

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

{ curly braces } and double quotes

You can reference variables directly inside of double quotes; this often times makes code easier to read and nicer to look at. Example:

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

There are however instances when doing the above can give unexpected results. The curly braces help to keep that to a minimum and is just a good practice to get into – they clearly specify which variable you mean to reference.

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

in_array($needle, $haystack)

in_array is simply a way to check whether or not a value is present in an array. If the value is found then the function returns TRUE if not then FALSE.

The line…

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

…therefore sets $repeat to either TRUE or FALSE.

Ternary Operator

The ternary operator is effectively a short hand if...else statement.

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

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

In your case we use it to check if $repeat is TRUE (i.e. the current coordinate is present in the already visited coordinates array). If it is TRUE then we output REPEATn or n by itself if it isn’t.

echo ($repeat) ? " REPEATn" : "n";

The whole line…

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

…then outputs the $current_point followed by either REPEATn or n.



Source: stackoverflow