我有一个像这样的数组:
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') 等这样的“踢入列表”来创建这些块,那就太好了。
非常感谢!
这是一个
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' => '...'),
),
),
)
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
为了避免查找第一级索引或维护计数器变量的乏味,只需将引用推入结果数组即可。 这样,您可以轻松地将子行推入父行。 结果将是一个索引数组,其中
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