Как преобразовать массив строк в массив кусков с переменным размером кусков?

Как преобразовать следующий массив:

[
"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 было бы идеально, если бы не тот факт, что куски имеют переменные размеры. Префиксы известны заранее, и каждый «чанк» будет иметь длину два или три.

0

Решение

Вы могли бы сделать это так (учитывая $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;
}

Предполагается, что ключи, которые должны заканчиваться в одном и том же подмассиве, располагаются в алфавитном порядке во входных данных, поэтому разрыв в следующем подмассиве происходит, когда этот порядок не поддерживается.

1

Другие решения

Это решение позволяет произвольно упорядочивать префиксы, сохраняя их в массиве в том порядке, в котором они ожидаются во входных данных (предполагается, что они находятся в $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
)
)

Демо на 3v4l.org

1

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',
),
)
1

Вы можете сделать это немного проще

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

демонстрация

1
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector