Giorgio
Giorgio

Reputation: 1613

Split an array with a regular expression

I'm wondering if it is possible to truncate an array by using a regular expression.

In particular I have an array like this one:

$array = array("AaBa","AaBb","AaBc","AaCa","AaCb","AaCc","AaDa"...);

I have this string:

$str = "AC";

I'd like the slice of $array from the start to the last occurrence of a string matching /A.C./ (in the sample, "AaCc" at index 5):

$result = array("AaBa","AaBb","AaBc","AaCa","AaCb","AaCc");

How can I do this? I thought I might use array_slice, but I don't know how to use a RegEx with it.

Upvotes: 2

Views: 949

Answers (3)

Brad Christie
Brad Christie

Reputation: 101604

Here's my bid

function split_by_contents($ary, $pattern){
  if (!is_array($ary)) return FALSE; // brief error checking

  // keep track of the last position we had a match, and the current
  // position we're searching
  $last = -1; $c = 0;

  // iterate over the array
  foreach ($ary as $k => $v){
    // check for a pattern match
    if (preg_match($pattern, $v)){
      // we found a match, record it
      $last = $c;
    }
    // increment place holder
    $c++;
  }

  // if we found a match, return up until the last match
  // if we didn't find one, return what was passed in
  return $last != -1 ? array_slice($ary, 0, $last + 1) : $ary;
}

Update

My original answer has a $limit argument that served no purpose. I did originally have a different direction I was going to go with the solution, but decided to keep it simple. However, below is the version that implements that $limit. So...

function split_by_contents($ary, $pattern, $limit = 0){
  // really simple error checking
  if (!is_array($ary)) return FALSE;

  // track the location of the last match, the index of the
  // element we're on, and how many matches we have found
  $last = -1; $c = 0; $matches = 0;

  // iterate over all items (use foreach to keep key integrity)
  foreach ($ary as $k => $v){

    // text for a pattern match
    if (preg_match($pattern, $v)){

      // record the last position of a match
      $last = $c;

      // if there is a specified limit, capture up until
      // $limit number of matches, then exit the loop
      // and return what we have
      if ($limit > 0 && ++$matches == $limit){
        break;
      }
    }

    // increment position counter
    $c++;
  }

Upvotes: 4

Mark Baker
Mark Baker

Reputation: 212412

Assuming incremental numeric indices starting from 0

$array = array("AaBa","AaBb","AaBc","AaCa","AaCb","AaCc","AaDa");
$str = "AC";

$regexpSearch = '/^'.implode('.',str_split($str)).'.$/';
$slicedArray = array_slice($array,
                           0,
                           array_pop(array_keys(array_filter($array,
                                                             function($entry) use ($regexpSearch) { 
                                                                 return preg_match($regexpSearch,$entry); 
                                                             }    
                                                            )
                                               )
                                    )+1
                          );

var_dump($slicedArray);

PHP >= 5.3.0 and will give a

Strict standards: Only variables should be passed by reference

And if no match is found, will still return the first element.

Upvotes: 1

SpoonNZ
SpoonNZ

Reputation: 3829

I think the easiest way might be with a foreach loop, then using a regex against each value - happy to be proven wrong though!

One alternative could be to implode the array first...

$array = array("AaBa","AaBb","AaBc","AaCa","AaCb","AaCc","AaDa"...);
$string = implode('~~',$array);
//Some regex to split the string up as you want, guessing something like
// '!~~A.C.~~!' will match just what you want?
$result = explode('~~',$string);

If you'd like a hand with the regex I can do, just not 100% on exactly what you're asking - the "A*C*"-->"AaCc" bit I'm not too sure on?

Upvotes: 1

Related Questions