在平面数组中遇到非日期值时,创建日期分组子数组



我有这个数组,我想创建一个包含日期值的新数组,但是每当达到STOPSALES值时,创建一个新的子数组/组,并且只存储日期值。

[0]=>
string(10) "2023-03-10"
[1]=>
string(10) "2023-03-11"
[2]=>
string(10) "2023-03-12"
[3]=>
string(10) "2023-03-13"
[4]=>
string(10) "2023-03-14"
[5]=>
string(10) "2023-03-15"
[6]=>
string(9) "STOPSALES"
[7]=>
string(9) "STOPSALES"
[8]=>
string(9) "STOPSALES"
[9]=>
string(9) "STOPSALES"
[10]=>
string(9) "STOPSALES"
[11]=>
string(9) "STOPSALES"
[12]=>
string(9) "STOPSALES"
[13]=>
string(9) "STOPSALES"
[14]=>
string(9) "STOPSALES"
[15]=>
string(9) "STOPSALES"
[16]=>
string(9) "STOPSALES"
[17]=>
string(10) "2023-03-27"
[18]=>
string(10) "2023-03-28"
[19]=>
string(10) "2023-03-29"
[20]=>
string(10) "2023-03-30"
[21]=>
string(10) "2023-03-31"
[22]=>
string(10) "2023-04-01"
[23]=>
string(10) "2023-04-02"
[24]=>
string(10) "2023-04-03"

我希望有这样的结果

[0]=>
string(10) "2023-03-10"
[1]=>
string(10) "2023-03-11"
[2]=>
string(10) "2023-03-12"
[3]=>
string(10) "2023-03-13"
[4]=>
string(10) "2023-03-14"
[5]=>
string(10) "2023-03-15"
[1]=>
string(10) "2023-03-27"
[1]=>
string(10) "2023-03-28"
[2]=>
string(10) "2023-03-29"
[3]=>
string(10) "2023-03-30"
[4]=>
string(10) "2023-03-31"
[5]=>
string(10) "2023-04-01"
[6]=>
string(10) "2023-04-02"
[7]=>
string(10) "2023-04-03"

我用foreach和if语句试了几个小时,但就是找不到方法。

这是我最好的办法。

$res = [];
$num = 0;
foreach ($array as $go) {
if ($go == 'STOPSALES') {
continue; 
} else {
$num = $num+1;
array_push($res[$num],$go);
}
}
var_export($result);

将引用变量压入结果数组,这样您就不需要维护/增加计数器变量和切换布尔变量。

下面的代码只会在遇到STOPSALES值时销毁引用。对于所有其他值,它要么创建并推入一个新引用,要么简单地将新值推入现有引用。

代码(演示):

$result = [];
foreach ($array as $v) {
if ($v === 'STOPSALES') {
unset($ref); // no longer used (if it even existed)
continue; // nothing more to do; go to next iteration
}
if (!isset($ref)) {
$ref = [$v]; // declare/populate new reference with current value
$result[] = &$ref; // push new reference into result at next available index
} else {
$ref[] = $v; // add current value to current reference/group because is a consecutive date value
}
}
var_export($result);

因为你正在处理一个索引输入数组,你可以有条件地检查前一个索引的值,并在推入当前值时碰撞结果数组组的第一级键。

代码(演示):

$result = [];
$k = 0;
foreach ($array as $i => $v) {
if ($v !== 'STOPSALES') {
if (($array[$i - 1] ?? null) === 'STOPSALES') {
++$k;
}
$result[$k][] = $v;
}
}
var_export($result);

这是实现你想要的东西的一种方法:

$array = [
"2023-03-10",
"2023-03-11",
"2023-03-12",
"2023-03-13",
"2023-03-14",
"2023-03-15",
"STOPSALES",
"STOPSALES",
"STOPSALES",
"STOPSALES",
"STOPSALES",
"STOPSALES",
"STOPSALES",
"STOPSALES",
"STOPSALES",
"STOPSALES",
"STOPSALES",
"2023-03-27",
"2023-03-28",
"2023-03-29",
"2023-03-30",
"2023-03-31",
"2023-04-01",
"2023-04-02",
"2023-04-03",
];
$result = []; // array of subarrays
$i = 0; // incremented after a "STOPSALES"
$wasStopSales = FALSE; // to avoid creating multiple empty arrays with consecutive "STOPSALES"
foreach ($array as $element) {
if ($element == 'STOPSALES') {
if (!$wasStopSales) { // if that's the first consecutive "STOPSALES"
++$i; // let's move to another subarray
}
$wasStopSales = TRUE;
continue;
}
$result[$i][] = $element; // add the current element to the current subarray
$wasStopSales = FALSE; // last value wasn't a "STOPSALES"
}
var_dump($result);

结果是:

array (size=2)
0 => 
array (size=6)
0 => string '2023-03-10' (length=10)
1 => string '2023-03-11' (length=10)
2 => string '2023-03-12' (length=10)
3 => string '2023-03-13' (length=10)
4 => string '2023-03-14' (length=10)
5 => string '2023-03-15' (length=10)
1 => 
array (size=8)
0 => string '2023-03-27' (length=10)
1 => string '2023-03-28' (length=10)
2 => string '2023-03-29' (length=10)
3 => string '2023-03-30' (length=10)
4 => string '2023-03-31' (length=10)
5 => string '2023-04-01' (length=10)
6 => string '2023-04-02' (length=10)
7 => string '2023-04-03' (length=10)

如果你需要更多的细节,请随时问我。

我已经自学了如何使用生成器进行这样的动态分组。听起来有点夸张,但它非常可读,并且如果您不需要一次使用所有组,则可以非常有效。如果你这样做,你可以使用iterator_to_array()得到所有的。

function groupBySTOPSALES(array $input) {
$group = [];
foreach ($input as $el) {
if ($el == 'STOPSALES') {
if (count($group)) {
yield $group;
$group = [];
}
}
else {
$group[] = $el;
}
}
if (count($group)) {
yield $group;
}
}
$grouper = groupBySTOPSALES($array);
$allGroups = iterator_to_array($grouper);
print_r($allGroups);

生成器函数不需要太多的状态。只是一个$group。没有&参考,也没有分组大小计数。因为它是一个发电机。而且他们很酷。

但是不要只是相信我。阅读PHP生成器并使用它。

最新更新