【问题标题】:Split an array with a regular expression使用正则表达式拆分数组
【发布时间】:2012-01-17 19:46:49
【问题描述】:

我想知道是否可以使用正则表达式截断数组。

特别是我有一个这样的数组:

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

我有这个字符串:

$str = "AC";

我想要$array 的片段,从开始到最后出现匹配/A.C./ 的字符串(在示例中,索引5 处的“AaCc”):

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

我该怎么做?我想我可能会使用array_slice,但我不知道如何使用它。

【问题讨论】:

  • 不太清楚你想要什么。您的模式描述似乎更像是fnmatch() glob。如果您只想过滤列表或提取连续范围的匹配项,那么它是模棱两可的。
  • /A*C*/i 也会匹配一个空字符串。您确定应该为此任务使用正则表达式吗?
  • $str 和模式应该是什么关系?
  • 抱歉,我更新了我提到的问题 "/A.C./" A 后跟只有 1 个随机字符,然后是 C 后跟只有 1 个随机字符。
  • @Giorgio:我对原始版本中的代码进行了更新(因此请确保使用该代码),如果您有兴趣,还发布了一个替代版本。

标签: php regex arrays


【解决方案1】:

这里是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;
}

更新

我的原始答案有一个 $limit 参数,没有任何用处。我最初确实有一个不同的方向,我打算采用该解决方案,但决定保持简单。但是,下面是version that implements that $limit。所以...

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

【讨论】:

  • 使用类似for($key = sizeof($array)-1; $key>=0; $key--) 的东西可能会更有效一些 - 从数组的尾部开始,然后在第一个匹配时返回。
  • @SpoonNZ:虽然是这样,但我不确定将传递什么样的数组。对于钥匙无关紧要的事情,当然。但如果他们通过array('aa' => 'AaAa', 'ab' => 'AaBb', 'ac' => 'AaCc'); 会很臭。
【解决方案2】:

我认为最简单的方法可能是使用 foreach 循环,然后对每个值使用正则表达式 - 不过很高兴被证明是错误的!

另一种方法是先内爆数组...

$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);

如果您想使用我能做的正则表达式,但不是 100% 完全符合您的要求 - "A*C*"-->"AaCc" 位我不太确定?

【讨论】:

    【解决方案3】:

    假设从 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 并且会给出一个

    严格的标准:只能通过引用传递变量

    如果没有找到匹配,仍然会返回第一个元素。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-06-04
      • 2020-01-14
      • 1970-01-01
      • 1970-01-01
      • 2021-04-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多