Home > other >  Create grouped subarrays of dates when non-date values are encountered in a flat array
Create grouped subarrays of dates when non-date values are encountered in a flat array

Time:01-08

I have this array, and I would like to make a new array with date values, but whenever a STOPSALES value is reached, create a new subarray/group, and only store date values.

[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"

I will like to have this result

[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"

I tried for hours with foreach and if statments, but can't find the way.

This was my best aproach.

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

CodePudding user response:

Push reference variables into the result array so that you don't need to maintain/increment a counter variable and a toggling boolean variable.

The following code will only destroy the reference when a STOPSALES value is encountered. For all other values, it will either create and push a new reference or simply push the new value into the existing reference.

Code: (Demo)

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

Since you are dealing with an indexed input array, you can conditionally check the value if the previous index and bump the result array group's first level key when pushing the current value.

Code: (Demo)

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

CodePudding user response:

Here is one way of achieving what you want:

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

The result is:

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)

Feel free to ask me if you need more details.

CodePudding user response:

I've taught myself to do dynamic grouping like this with generators. Sounds like overkill, but it's very readable, AND can be very efficient if you don't need all the groups at once. And if you do, you can just use iterator_to_array() to get all of them.

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

Your generator function doesn't need much state. Just a $group. And no & refs, or group size counting. Because it's a generator. And they're cool.

But don't just believe me. Read about PHP generators and play with it.

  • Related