1

I am trying to filter and reindex this array. My original array is $_SESSION['ShowingRequests'].
I've tried

array_values(array_filter($_SESSION['ShowingRequests']))

and

array_values(array_filter($_SESSION['ShowingRequests']['ListingKey']))
array_values(array_filter($_SESSION['ShowingRequests']['Key']))

but it won't reach the second level of the array. I want it to go from this

Array
(
    [ListingKey] => Array
        (
            [1] => 97826889139
            [2] => 97820967049
            [4] => 97825243774
            [5] => 97824864611
        )
    [Key] => Array
        (
            [1] => 2
            [2] => 3
            [4] => 5
            [5] => 6
        )
)

to this

Array
(
    [ListingKey] => Array
        (
            [0] => 97826889139
            [1] => 97820967049
            [2] => 97825243774
            [3] => 97824864611
        )
    [Key] => Array
        (
            [0] => 2
            [1] => 3
            [2] => 5
            [3] => 6
        )
)
xjx424
  • 173
  • 2
  • 12

2 Answers2

3

PHP arrays are not indexed, because they are not real arrays. They are in fact ordered hashmaps and as such you should not really care about the keys here. Iterating over these arrays is trivial and does not require using array_values at all.

foreach ($_SESSION['ShowingRequests']['ListingKey'] as $key => $value) {
    echo "$key => $value\n";
}

Would give you...

        1 => 97826889139
        2 => 97820967049
        4 => 97825243774
        5 => 97824864611

Where you get the name of the key and the value for each element in the array using the foreach construct.

In any case you have to remember that both array_values and array_filter are non-destructive functions. They return a new array. They do not modify the array by reference. As such you must assign the return value if you want to modify the existing array. They also do not work recursively.

$_SESSION['ShowingRequests']['ListingKey'] = array_values(array_filter($_SESSION['ShowingRequests']['ListingKey']));
$_SESSION['ShowingRequests']['Key'] = array_values(array_filter($_SESSION['ShowingRequests']['Key']));
$_SESSION['ShowingRequests'] = array_values(array_filter($_SESSION['ShowingRequests']));
Sherif
  • 11,786
  • 3
  • 32
  • 57
  • If you remove keys from `$_SESSION['ShowingRequests']` (as in the first line of the last code-block), the next two lines won't find those keys any longer. – hakre Jan 07 '13 at 22:49
  • You're correct that should have been done the other way around. Will fix that, thanks :) – Sherif Jan 07 '13 at 22:58
  • If you do it the other way round, you still destroy it. I just would skip the (previously first) line. – hakre Jan 07 '13 at 22:59
  • Assigning the return value was what I was missing. Also, doesn't work for just $_SESSION['ShowingRequests']. Had to assign the value for each $_SESSION['ShowingRequests']['ListingKey'] and $_SESSION['ShowingRequests']['Key']. Thanks Googleguy – xjx424 Jan 07 '13 at 23:03
  • Well, using it on `$_SESSION['ShowingRequests']` just means you lose those non-numeric keys (i.e. `ListingKey` and `Key`) and they become 0 and 1, respectively. – Sherif Jan 07 '13 at 23:05
  • In any case I still argue that there is absolutely no need for what you're doing whatsoever. You have to ask yourself *why do I need to use `array_values` here at all* and I assure you that it will rarely ever serve any benefit to your code whatsoever since in a PHP array a key has absolutely no bearing on the order of an element at all. – Sherif Jan 07 '13 at 23:06
  • Basically because I am using a for($i=0;$i – xjx424 Jan 07 '13 at 23:48
  • Right, that's specifically the problem the [foreach](http://php.net/foreach) constructs solves for you ;) – Sherif Jan 07 '13 at 23:50
  • I see what you're saying. You would still get the accurate count for an array using count($_SESSION['ShowingRequests']) even if the highest key value is higher than the count of the array. And even if your array keys were 1, 5, 6, 8 you would not have empty results in your loop. – xjx424 Jan 08 '13 at 00:04
  • That's correct. foreach comes with a **promise** that it will *always iterate over every element in the array* that you supplied. *In PHP an array's keys have absolutely no control over the order of the elements in the array whatsoever*. Take the following example where we have `$array = array(100 => 1, 1 => 2, -19 => 3, 7000 => 4, 'foo' => 5);` and we want to iterate over each element in that array with: `foreach($array as $v) echo "$v,";` we get `1,2,3,4,5`. Even if we `unset($array[-19]);` and do `foreach($array as $v) echo "$v,";` we get `1,2,4,5` as expected :) – Sherif Jan 08 '13 at 00:13
0

Is your issue to assign the filtered values back to the same key?

foreach (['ListingKey', 'Key'] as $key) 
{
    $_SESSION['ShowingRequests'][$key] = array_values(
        array_filter($_SESSION['ShowingRequests'][$key])
    );
}

Here some demonstration how it works with a helper function just to make that more visible

function array_filter_values($var) {
    return array_values(array_filter($var));
}

foreach (['ListingKey', 'Key'] as $key) 
{
    $_SESSION['ShowingRequests'][$key] = 
        array_filter_values($_SESSION['ShowingRequests'][$key])
    ;
}

Here is an example without that helper function but with an alias of which I had thought it might make that more easy to understand but apparently not:

foreach (['ListingKey', 'Key'] as $key) 
{
    $var = &$_SESSION['ShowingRequests'][$key];
    $var = array_values(array_filter($var));
    unset($var);
}

This example code is using an alias to the variable you want to change (here the part of the array you want to change). This probably makes it more visible how it works. Because it is an alias, unset is used to remove the alias, it should not be re-used in the next iteration or after the iteration has finished.

hakre
  • 193,403
  • 52
  • 435
  • 836
  • For what it's worth this is a really bad solution to the problem as you asigned $_SESSION['ShowingRequests'][$key] by reference only to completely discard the reference and reassign by value. Basically you took an unnecessary step and you actually cause more confusion and potential for error. Remove the line `$var = &$_SESSION['ShowingRequests'][$key];` and replacing the other two lines with `$_SESSION['ShowingRequests'][$key] = array_values(array_filter($_SESSION['ShowingRequests'][$key]));` actually does the right thing. – Sherif Jan 07 '13 at 22:43
  • @GoogleGuy: The reference is not discarded. The alias is used until `unset`. See http://eval.in/6110 - You are probably right that for those who don't think *Alias* but *Reference* might mix that with other things and then it's hard to understand. I'll make the other version, too. – hakre Jan 07 '13 at 22:51
  • No, it's discarded :) I also have no idea what you mean by *Alias* there since what you have is absolutely a **Reference** and it also serves no point whatsoever since your code does exactly what you want it to do with out that unnecessary and wrong use of reference :) See http://php.net/references for more on what references are in PHP. Most people have a strong misconceptions about what references do in PHP and why they should use them. I would argue that their use cases are so rare that in 8 years of PHP I think I used them once :) – Sherif Jan 07 '13 at 23:02
  • @GoogleGuy: I just did use them to give each array entry another label. Perfectly fine if you ask me. And I don't see any misconception in my end honestly. – hakre Jan 07 '13 at 23:14
  • Oh, I"m not suggesting that your code doesn't work. I'm suggesting your use of references there is unnecessary. Thus the misconception about what a reference does. You do not need a reference there to do what you want done. As you can see `foreach($_SESSION['ShowingRequests'] as $key => $value) $_SESSION['ShowingRequests'][$key] = array_values(array_filter($value));` does exactly what you want and without references :) Cheers – Sherif Jan 07 '13 at 23:17
  • I know that I don't need it, just wanted to show which part in the array would have needed to be changed if - and only if - there was a problem understanding how to put the filtered values back into the array. – hakre Jan 07 '13 at 23:18
  • Well, unfortunately I find that references don't reveal anything *more elaborately*. In fact, references conceal things away from the user that they should otherwise clearly see from the context of code. Unfortunately a reference has no context and no way to know at runtime how the variable became a reference or even to what it references or if it even is a reference (at least non that are intuitive in any meaningful way). References are obscure, unnecessary, and archaic bits of the engine one should really avoid at all costs. I posit that they actually serve no practical purpose in your code. – Sherif Jan 07 '13 at 23:23
  • Yes next time I name it: `$variableYouWantToChange`. And I make it a function parameter. Passed by reference. – hakre Jan 07 '13 at 23:31