RandomWhiteTrash
RandomWhiteTrash

Reputation: 4014

PHP foreach that returns keys only

Theoretical question that perhaps does not make any sense but still, maybe there is a clever answer.

I want to iterate through array and get its keys and to something with them. A quick example of what I do:

foreach($array as $key => $value) {
    $other_array[$key] = 'something';
}

Now, PHP Mess Detector screams that $value is unused in this scope. Therefore I was thinking that perhaps this is not the best way to access keys of my array.

Any idea how to do it without unnecessarily taking out values out of my array? Does it have any significant performance impact ... or perhaps I am just being paranoid and should carry on without wasting anyone's time with stupid questions :).

Upvotes: 58

Views: 33115

Answers (7)

atwixtor
atwixtor

Reputation: 804

If you are using an XML ruleset:

    <rule ref="rulesets/unusedcode.xml/UnusedLocalVariable">
        <properties>
            <property name="allow-unused-foreach-variables" value="true" />
        </properties>
    </rule>

Upvotes: 2

18C
18C

Reputation: 2110

Hack by 18C :-)

In construction as $key=>$value, the $value is first assigned in PHP before assigning $key.

$array=[1,3,6,10];

foreach($array as $k => $k) 
   print($k.'<br/>');

For your code:

foreach($array as $key => $key) 
{
    $other_array[$key] = 'something';
}

Btw. do not use: foreach($array as $k => &$k). It can disrupt your array.

Upvotes: 2

AbcAeffchen
AbcAeffchen

Reputation: 14987

Just ignore this message.

In PHP the way you used foreach is the fastest. It is right, that you should avoid unused variables, but in this case you cannot avoid it, without losing some performance.

E.g. foreach(array_keys($arr) as $key) is about 50% to 60% slower
than foreach($arr as $key => $notUsed).

This issue of phpmd is already reported here and there is also already a pull request here.

Until phpmd is updated you can also use this little hack

In the file /src/main/php/PHPMD/Rule/UnusedLocalVariable.php in the method collectVariables(..) (line 123 in my case) replace

if ($this->isLocal($variable))

by

if ($this->isLocal($variable) && !($this->isChildOf($variable, 'ForeachStatement') && $variable->getName() === '$notUsed'))

This will stop phpmd from reporting $notUsed anywhere inside a foreach loops.

UPDATE: The recommendation above assumes PHP 5.6 (the relevant version at the time of writing this answer). But time went by and now using PHP 7.2 it seems to be the other way around. As always it depends on the exact use case, but for associative arrays with less than 100.000 keys it is faster to store array_keys($arr) in a variable and use this in a foreach loop.

Upvotes: 20

botris
botris

Reputation: 161

It's valid PHP code, don't fix the code, but fix PHP MD. There is a config in PHP MD 2.2 And needs this rule:

<properties>
    <property
        name="allow-unused-foreach-variables"
        description="Allow unused variables in foreach language constructs."
        value="false" />
</properties>

Upvotes: 5

Darksynx
Darksynx

Reputation: 80

loop to avoid a foreach in a while.

$a = ['1','A','B','12','ui'];

 while(true) { sleep(1);
    $b = next($a) ? current($a): reset($a);
    echo key($a) , ':' , $b , PHP_EOL;
 }

Upvotes: 1

core1024
core1024

Reputation: 1882

If you want to set all keys to certain value you can just do it this way:

$array = array(
        'foo'=> 'oldval1',
        'bar'=> 'oldval2',
        'baz'=> 'oldval3'
);

$other_array = array_fill_keys(array_keys($array), 'something');
print_r($other_array);

This will produce:

Array
(
    [foo] => something
    [bar] => something
    [baz] => something
)

Upvotes: 1

inquam
inquam

Reputation: 12932

You could do something like this

foreach(array_keys($array) as $key) {
 // do your stuff
}

That would make the foreach iterate over an array consisting of the keys from your array instead of the actual array. Note that it's probably not better from a performance standpoint though.

Upvotes: 89

Related Questions