[Okta Webinar] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 480
  • Last Modified:

PHP: Remove Items from Array Using REGEX

Using PHP, how can I remove all items that do not match a regular expression?

This code works exactly as I want it to however I think it could be dramatically simplified.

<pre>
<?php

$l = array('xyz/abc/Item_10.txt','xyz/abc/Item_14.txt','xyz/abc/Item_5.txt','xyz/abc/Item_x.txt','xyz/abc/Item_110.txt','xyz/abc/Item_133.txt','xyz/abc/Item_7.txt');

foreach ($l as $key => $value) {
 if(!testAbove12($value)) unset($l[$key]);
}

print_r($l);

function testAbove12($str) {
    return preg_match('@/Item_(\d+)@',$str,$m) ? ((int)$m[1]>=12) : false;
}

?>
</pre>

Open in new window

0
hankknight
Asked:
hankknight
6 Solutions
 
Dave BaldwinFixer of ProblemsCommented:
I don't see how.  You have 1 foreach and 1 function.  I would not try to combine them.  Let PHP's optimizer take care of that for you.  I rarely change actual working code anyway.
0
 
Terry WoodsIT GuruCommented:
If you have PHP >= 5.3.0:

$result = preg_filter('@/Item_0*(1[3-9]|([2-9]|1\d)\d+)@','$0', $l);

Open in new window


But it's not very intuitive code to read. I'd recommend going with what you've got.
0
 
Ray PaseurCommented:
Please post the input data and the desired output data.  We can surely find a way to bridge the gap, but there is no use in looking at PHP scripts that do not work correctly.  The data will reveal the answer.  Thanks. ~Ray
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
acbxyzCommented:
1) You can replace the for loop by http://php.net/manual/en/function.array-filter.php
2) You can omit the subfunction and integrate its content directly as another if in the for loop or as anonymous function in array_filter.

It is not very complicated to get much actions in small code. But small code is not always the best way.See
0
 
Ray PaseurCommented:
Looking at this with fresh eyes, it seems that the test cases may not be complete.  See the output from this script which is constructively the same as the original, but spaced neatly and commented so the intent of the code is clearer to the reader.

I have never timed the difference in array_filter() vs foreach() with a separate function call, however I doubt that we would find a meaningful difference in the speed of these two constructs.  By "meaningful" I would mean a difference that could be observed by a human client, discerned in the larger context of the web application.  Tiny code tweaks like this are usually "milking a mouse" -- there is substantial time and effort required for very little resulting benefit.  Better to go milk the cow, which in the case of web applications is the optimization of the data model, consisting of the data base and the file system.  

If you want a timer class that can be used to isolate and record the speed of code blocks, please let me know.

Anyway, best of luck with it, ~Ray

<pre>
<?php

// TEST DATA FROM THE POST AT EE
$l = array
( 'xyz/abc/Item_10.txt'
, 'xyz/abc/Item_14.txt'
, 'xyz/abc/Item_5.txt'
, 'xyz/abc/Item_x.txt'
, 'xyz/abc/Item_110.txt'
, 'xyz/abc/Item_133.txt'
, 'xyz/abc/Item_7.txt'

// SOME OTHER TEST DATA
, 'xyz/abc/ITEM_17.txt'
, 'xyz/abc/Item_72A.txt'
, 'xyz/abc/Item_13-34.txt'
, 'xyz/abc/Item_17/evilhack.exe'

)
;

foreach ($l as $key => $value)
{
    if(!testAbove12($value))
    {
        echo PHP_EOL . $value . ' FAILED THE TEST ABOVE 12';
        unset($l[$key]);
    }
    else
    {
        echo PHP_EOL . $value . ' OK';
    }
}

echo PHP_EOL;
print_r($l);

function testAbove12($str)
{
    $regex
    = '#'        // REGEX DELIMITER
    . '/Item_'   // LITERAL STRING
    . '('        // START GROUP
    . '\d+'      // DIGITS
    . ')'        // END GROUP
    . '#'        // REGEX DELIMITER
    ;
    return preg_match($regex, $str, $m) ? ( (int)$m[1] >= 12 ) : FALSE;
}

?>
</pre>

Open in new window

0
 
Ray PaseurCommented:
0
 
käµfm³d 👽Commented:
@acbxyz

While I agree that code should not be simplified to the point of obscurity, I don't think it's fair to provide a link to a concept whose intent is to *actually* reduce the coherence of a piece of code. The whole point of an obfuscation contest is to make code unintelligible. I think a link where someone said, "Hey check out this nifty regex I made," followed by a, "Sweet! WTF does it do?" would have been more to the point  = )
0
 
skullnobrainsCommented:
@ray + offtopic

<quote>
I have never timed the difference in array_filter() vs foreach() with a separate function call, however I doubt that we would find a meaningful difference in the speed of these two constructs.
</quote>

the difference is not really about the iterator, but compiling the regexp over and over is expensive. using a precompiled regexp, the difference is likely to be little to none.

in this specific case, nothing mesurable will change unless the array gets REALLY huge so it probably does not matter

but the fastest would likely be not to use a regexp at all, since you can achieve roughly the same thing with a couple of strpos() calls, a substring and a numeric comparison, and possibly much simpler if the data is actually that well normalised

i love this dirty one : foreach($l as $k => $v)if(!substr(strrchr($v,'_'),1) > 12)unset($l[$k]);
0

Featured Post

Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now