Как преобразовать следующий массив:
[
"prefix1 foo",
"prefix2 bar",
"prefix1 aaa",
"prefix2 bbb",
"prefix3 ccc",
"prefix1 111",
"prefix2 222"]
в следующую структуру данных:
[
[
"prefix1" => "foo",
"prefix2" => "bar"],
[
"prefix1" => "aaa",
"prefix2" => "bbb",
"prefix3" => "ccc"],
[
"prefix1" => "111",
"prefix2" => "222"],
]
array_chunk было бы идеально, если бы не тот факт, что куски имеют переменные размеры. Префиксы известны заранее, и каждый «чанк» будет иметь длину два или три.
Вы могли бы сделать это так (учитывая $input
):
$result = [];
$prev = $input[0];
foreach($input as $line) {
list($key, $value) = explode(" ", $line);
if ($key < $prev) $result[] = [];
$result[count($result)-1][$key] = $value;
$prev = $key;
}
Предполагается, что ключи, которые должны заканчиваться в одном и том же подмассиве, располагаются в алфавитном порядке во входных данных, поэтому разрыв в следующем подмассиве происходит, когда этот порядок не поддерживается.
Это решение позволяет произвольно упорядочивать префиксы, сохраняя их в массиве в том порядке, в котором они ожидаются во входных данных (предполагается, что они находятся в $input
):
$prefixes = ['prefix1', 'prefix2', 'prefix3'];
$output = array();
$lastidx = count($prefixes);
foreach ($input as $item) {
list($prefix, $value) = explode(' ', $item);
$index = array_search($prefix, $prefixes);
if ($index < $lastidx) $output[] = array();
$output[count($output)-1][$prefix] = $value;
$lastidx = $index;
}
print_r($output);
Для вашего образца входной выход:
Array (
[0] => Array (
[prefix1] => foo
[prefix2] => bar
)
[1] => Array (
[prefix1] => aaa
[prefix2] => bbb
[prefix3] => ccc
)
[2] => Array (
[prefix1] => 111
[prefix2] => 222
)
)
isset()
быстрее чем array_search()
Код: (демонстрация)
$array = [
"prefix1 foo",
"prefix2 bar",
"prefix1 aaa",
"prefix2 bbb",
"prefix3 ccc",
"prefix1 111",
"prefix2 222"];
foreach ($array as $v) {
[$prefix, $value] = explode(' ', $v, 2); // explode and perform "array destructuring"if (isset($batch[$prefix])) { // check if starting new batch
$result[] = $batch; // store old batch
$batch = [$prefix => $value]; // start new batch
} else{
$batch[$prefix] = $value; // store to current batch
}
}
$result[] = $batch; // store final batch
var_export($result);
или же
foreach ($array as $v) {
[$prefix, $value] = explode(' ', $v, 2);
if (isset($batch[$prefix])) {
$result[] = $batch;
unset($batch);
}
$batch[$prefix] = $value;
}
$result[] = $batch;
Выход:
array (
0 =>
array (
'prefix1' => 'foo',
'prefix2' => 'bar',
),
1 =>
array (
'prefix1' => 'aaa',
'prefix2' => 'bbb',
'prefix3' => 'ccc',
),
2 =>
array (
'prefix1' => '111',
'prefix2' => '222',
),
)
Вы можете сделать это немного проще
$res = [];
foreach ($array as $v) {
list($prefix, $value) = explode(' ', $v, 2);
$res[$prefix][] = [$prefix => $value];
}
print_r($res);
// if you want numeric index
$res = array_values($res);
print_r($res);