查找以数组中的某个字符串开头的对象键

时间:2017-08-03 11:08:38

标签: php arrays loops

注意:很明显,这可以通过多个嵌套foreach()循环“轻松”完成,但我正在寻找一种更便宜的方式(如果可能的话,还可以减少spagetti)。

给定像这样的对象的数据数组:

$data (array)
   [] (obj)
      ->id
      ->name
      ->a_one
      ->a_two
      ->b_three
      ->b_four
      ->c_five
   [] (obj)
      ...

和这个匹配前缀数组:

$prefixes (array)
   [] (str) "a_"
   [] (str) "b_"
   [] (str) "c_"

如何找到(并取消设置)$data中所有以$prefixes之一开头的所有对象的所有属性,而不使用多个foreach()循环?

使用foreach()的解决方案:

foreach($data as $datakey => $obj) {
   foreach($prefixes as $prefix) {
      foreach($obj as $property => $value) {
         if(strpos($property, $prefix) === 0) {
            unset($data[$datakey]->{$property});
         }
      }
   }
}

有更好的方法吗?

3 个答案:

答案 0 :(得分:1)

构造一个匹配所有前缀的正则表达式模式,并针对正则表达式检查每个键:

$pattern = "^(" . join("|", $prefixes) . ")";
foreach($data as $datakey => $obj) {

foreach($data as $datakey => $obj) {
    foreach($obj as $property => $value) {
        if (preg_match($pattern, $property))
            ...
    }
}

这仍然需要两个循环,但没有冗余;数据中的每个对象只检查一次。如果你想找到一种方法来循环遍历所有对象的内容而不需要两个PHP循环,那么它仍然需要同样多的步骤。您的问题中的代码多次循环每个对象(每个前缀一次),这确实是多余的。

答案 1 :(得分:1)

不确定您是否愿意这样做,但是;

$prefixes = ['a_', 'b_'];

$filtered = array_map(function($object) use ($prefixes) {
    return unsetPrefixedProperties($object, $prefixes);
}, $data);

function unsetPrefixedProperties($object, $prefixes) {
    $regex = '/('. implode('|', $prefixes) .').+/';
    foreach ($object as $key => $value) {
        if (preg_match($regex, $key)) {
            unset($object->{$key});
        } 
    }

    return $object;
}

类似于alexis基本上使用正则表达式进行匹配,无需循环遍历前缀。利用数组映射形成一个新的过滤对象数组,因为在我个人看来它似乎更清晰,最后将另一个循环提取到它自己的函数中只是为了提高可读性。

仍然不完美,但这只是一个开始。

修改:Sandbox Example

答案 2 :(得分:0)

Picasso java.lang.NoClassDefFoundError