数组到阻止列表

问题描述 投票:0回答:3

我有一个像这样的数组:

0 = Array('attr' => Array('class' => 'class1'), 'content'=>'class-1-content'),
1 = Array('attr' => Array(), 'content'=>'...'),
2 = Array('attr' => Array('class' => 'whatever'), 'content'=>'...'),
3 = Array('attr' => Array('class' => 'anything'), 'content'=>'...'),
4 = Array('attr' => Array(), 'content'=>'...'),
5 = Array('attr' => Array('class' => 'class2'), 'content'=>'...'),
6 = Array('attr' => Array('key' => 'more-here'), 'content'=>'...'),
7 = Array('attr' => Array('class' => 'class1'), 'content'=>'class-1-again'),
8 = Array('attr' => Array('another-attr' => ''), 'content'=>'...'),
9 = Array('attr' => Array(), 'content'=>'...'),
10 = Array('attr' => Array('class' => 'and-so-on'), 'content'=>'...'),
...

我想创建一个获取特定属性的功能(就像在我的例子中,所有类都等于“class1”或“class2”)并对它们进行分组,直到其他任何内容“启动”。基本上是为了创造这样的结果:

0 = Array(type='class1', 'content='class-1-content', block=Array(
    0 = Array('attr' => Array(), 'content'=>'...'),
    1 = Array('attr' => Array('class' => 'whatever'), 'content'=>'...'),
    2 = Array('attr' => Array('class' => 'anything'), 'content'=>'...'),
    3 = Array('attr' => Array(), 'content'=>'...')
),
1 = Array(type='class2', 'content'=>'content-class-2', block=Array( 
    0 = Array('attr' => Array('key' => 'more-here'), 'content'=>'...'),
),
2 = Array(type='class1', 'content'=>'class-1-again', block=Array( 
    0 = Array('attr' => Array('another-attr' => ''), 'content'=>'...'),
    1 = Array('attr' => Array(), 'content'=>'...'),
    2 = Array('attr' => Array('class' => 'and-so-on'), 'content'=>'...')
)

有人可以帮我弄清楚如何以最好的方式做到这一点吗?如果能够创建一个像 Array('class1', 'class2', 'class3') 等这样的“踢入列表”来创建这些块,那就太好了。

非常感谢!

php arrays
3个回答
1
投票

这是一个

convert
函数,可以按照您的指示组装数组。它将原始数组作为第一个参数,并使用正则表达式来匹配您的类作为第二个参数:

function convert($data, $pattern) {
    $result = array();
    foreach($data as $element) {
        if (array_key_exists("attr", $element) && 
                array_key_exists("class", $element["attr"]) && 
                preg_match($pattern, $element["attr"]["class"]) ) {
            $group = $element;
            // set the "type" key/value
            $group["type"] = $group["attr"]["class"];
            // remove the "class" key
            unset($group["attr"]["class"]);
            // remove the "attr" key, unless not empty
            if (sizeof($group["attr"]) == 0) {
                unset($group["attr"]);
            }
            // initialise "block" for collecting the next items
            $group["block"] = array();
            // add the group array to the result
            $result[] = $group;
        } else {
            if (!sizeof($result)) {
                // create a "pre" group if there was not yet a group:
                $result[] = array("type" => "pre", "content" => null, "block" => array());
            }
            // add to block
            $result[sizeof($result)-1]["block"][] = $element; 
        }
    }
    return $result;
}

// Set-up test data
$data = Array(
    Array('attr' => Array('class' => 'class1'), 'content'=>'class-1-content'),
    Array('attr' => Array(), 'content'=>'...'),
    Array('attr' => Array('class' => 'whatever'), 'content'=>'...'),
    Array('attr' => Array('class' => 'anything'), 'content'=>'...'),
    Array('attr' => Array(), 'content'=>'...'),
    Array('attr' => Array('class' => 'class2'), 'content'=>'class-2-content'),
    Array('attr' => Array('key' => 'more-here'), 'content'=>'...'),
    Array('attr' => Array('class' => 'class1'), 'content'=>'class-1-again'),
    Array('attr' => Array('another-attr' => ''), 'content'=>'...'),
    Array('attr' => Array(), 'content'=>'...'),
    Array('attr' => Array('class' => 'and-so-on'), 'content'=>'...')
);

// Call function on test data, grouping on class1 and class2
var_export (convert($data, "/^class[1-2]$/"));

上述脚本的输出是:

array (
    0 => array ('content' => 'class-1-content', 'type' => 'class1', 'block' => array (
        0 => array ('attr' => array (), 'content' => '...'),
        1 => array ('attr' => array ('class' => 'whatever'), 'content' => '...'),
        2 => array ('attr' => array ('class' => 'anything'), 'content' => '...'),
        3 => array ('attr' => array (), 'content' => '...'),
        ),
    ),
    1 => array ('content' => 'class-2-content', 'type' => 'class2', 'block' => array (
        0 => array ('attr' => array ('key' => 'more-here'), 'content' => '...'),
        ),
    ),
    2 => array ('content' => 'class-1-again', 'type' => 'class1', 'block' => array (
        0 => array ('attr' => array ('another-attr' => ''), 'content' => '...'),
        1 => array ('attr' => array (), 'content' => '...'),
        2 => array ('attr' => array ('class' => 'and-so-on'), 'content' => '...'),
    ),
  ),
)

...这是您指定的预期输出。

有一些健全性检查,以避免在

attr
键不仅具有组的
class
属性时删除它。这不会发生在您的测试数据中,但最好保持安全。

此外,如果数据不以要分组的元素开头(即示例中不是

class1
class2
情况),则会在结果中放置一个虚拟“预”组,以对这些孤立数组进行分组。一个例子:

$data = Array(
    Array('attr' => Array(), 'content'=>'...'),
    Array('attr' => Array('class' => 'whatever'), 'content'=>'...'), 
    Array('attr' => Array('class' => 'anything'), 'content'=>'...'), 
    Array('attr' => Array(), 'content'=>'...'),
    Array('attr' => Array('class' => 'class1'), 'content'=>'class-1-content'),
    Array('attr' => Array(), 'content'=>'...')
);

将产生以下输出:

array (
    0 => array ('type' => 'pre', 'content' => NULL, 'block' => array (
        0 => array ('attr' => array (), 'content' => '...'),
        1 => array ('attr' => array ('class' => 'whatever'), 'content' => '...'),
        2 => array ('attr' => array ('class' => 'anything'), 'content' => '...'),
        3 => array ('attr' => array (), 'content' => '...')
        ),
    ),
    1 => array ('content' => 'class-1-content', 'type' => 'class1', 'block' => array (
        0 => array ('attr' => array (), 'content' => '...'),
        ),
    ),
)

0
投票

这可以通过在当前阵列上使用

foreach()
来完成。然后,如果设置了
['attr']['class']
值,我们使用
class
 检查它是否以 
strpos()
开头。如果
strpos() === 0
我们将其添加为新的顶部数组元素,如果不是,我们使用简单的计数器 var 将其作为新的子数组元素添加到最后一个顶部数组元素,即。
$i

$arrays = Array(
  Array('attr' => Array('class' => 'class1'), 'content'=>'class-1-content'),
  Array('attr' => Array(), 'content'=>'...'),
  Array('attr' => Array('class' => 'whatever'), 'content'=>'...'),
  Array('attr' => Array('class' => 'anything'), 'content'=>'...'),
  Array('attr' => Array(), 'content'=>'...'),
  Array('attr' => Array('class' => 'class2'), 'content'=>'...'),
  Array('attr' => Array('key' => 'more-here'), 'content'=>'...'),
  Array('attr' => Array('class' => 'class1'), 'content'=>'class-1-again'),
  Array('attr' => Array('another-attr' => ''), 'content'=>'...'),
  Array('attr' => Array(), 'content'=>'...'),
  Array('attr' => Array('class' => 'and-so-on'), 'content'=>'...')
  );

$i=-1; // simple counter
$newArray=array();
foreach($arrays as $array){
  if (isset($array['attr']['class']) && (0 === strpos($array['attr']['class'], 'class'))) {
      $i++; // increase the counter
      $newArray[]=$array; // add a new array element
    }
  else {
      $newArray[$i]['block'][]=$array; // add a new sub array element
    }
}

示例在这里 - https://3v4l.org/U1V8n


0
投票

为了避免查找第一级索引或维护计数器变量的乏味,只需将引用推入结果数组即可。 这样,您可以轻松地将子行推入父行。 结果将是一个索引数组,其中

block
元素中包含索引子数组。 演示

$result = [];
foreach ($data as $row) {
    if (!isset($ref) || preg_match('/^class\d+$/', $row['attr']['class'] ?? '')) {
        unset($ref);
        $ref = ['type' => $row['attr']['class'], 'content' => $row['content'], 'block' => []];
        $result[] =& $ref;
        continue;
    }
    $ref['block'][] = $row;
}
var_export($result);

细分:

#initialize the result array
#loop the input array
#    if the current row qualifies as a group parent:
#        destroy the current group reference
#        declare a new group
#        push the new group as a reference into the result array
#    else
#        push the child row into the group's block array
#end of loop
© www.soinside.com 2019 - 2024. All rights reserved.