I have a dynamic array, each group of lines start with a specific code "S10.G00.00", "S10.G00.01", "S10.G00.02" ...
The array may be like this:
array:20 [▼
0 => "S10.G00.00.001,'www.mywebsite'"
1 => "S10.G00.00.002,'Company name'"
2 => "S10.G00.00.003,'v2.01'"
3 => "S10.G00.01.001,'492484944'"
4 => "S10.G00.01.002,'00029'"
5 => "S10.G00.01.003,'First name'"
6 => "S10.G00.01.004,'120 R CHARLES'"
7 => "S10.G00.01.005,'92200'"
8 => "S10.G00.02.001,'01'"
9 => "S10.G00.02.002,'first name'"
10 => "S10.G00.02.004,'[email protected]'"
11 => "S10.G00.02.005,'0750000000'"
12 => "S20.G00.05.001,'01'"
13 => "S20.G00.05.002,'01'"
14 => "S20.G00.05.003,'11'"
15 => "S20.G00.05.004,'5'"
16 => "S20.G00.05.010,'01'"
17 => "S10.G00.01.001,'492484944'"
18 => "S10.G00.01.002,'00029'"
19 => "S10.G00.01.003,'Last name'"
]
I would like to select each group of successive lines that start with the same code (the first 10 characters) and put them into an associative array.
The associative array should be like this :
array:5 [▼
0 => array:1 [▼
"S10.G00.00" => array:3 [▼
0 => "S10.G00.00.001,'www.mywebsite'"
1 => "S10.G00.00.002,'Company name'"
2 => "S10.G00.00.003,'v2.01'"
]
]
1 => array:1 [▼
"S10.G00.01" => array:5 [▼
0 => "S10.G00.01.001,'492484944'"
1 => "S10.G00.01.002,'00029'"
2 => "S10.G00.01.003,'First name'"
3 => "S10.G00.01.004,'120 R CHARLES'"
4 => "S10.G00.01.005,'92200'"
]
]
2 => array:1 [▼
"S10.G00.02" => array:4 [▼
0 => "S10.G00.02.001,'01'"
1 => "S10.G00.02.002,'first name'"
2 => "S10.G00.02.004,'[email protected]'"
3 => "S10.G00.02.005,'0750000000'"
]
]
3 => array:1 [▼
"S10.G00.05" => array:5 [▼
0 => "S20.G00.05.001,'01'"
1 => "S20.G00.05.002,'01'"
2 => "S20.G00.05.003,'11'"
3 => "S20.G00.05.004,'5'"
4 => "S20.G00.05.010,'01'"
]
]
4 => array:1 [▼
"S10.G00.01" => array:3 [▼
0 => "S10.G00.01.001,'492484944'"
1 => "S10.G00.01.002,'00029'"
2 => "S10.G00.01.003,'Last name'"
]
]
]
I have a dynamic array, each group of lines start with a specific code "S10.G00.00", "S10.G00.01", "S10.G00.02" ...
The array may be like this:
array:20 [▼
0 => "S10.G00.00.001,'www.mywebsite.com'"
1 => "S10.G00.00.002,'Company name'"
2 => "S10.G00.00.003,'v2.01'"
3 => "S10.G00.01.001,'492484944'"
4 => "S10.G00.01.002,'00029'"
5 => "S10.G00.01.003,'First name'"
6 => "S10.G00.01.004,'120 R CHARLES'"
7 => "S10.G00.01.005,'92200'"
8 => "S10.G00.02.001,'01'"
9 => "S10.G00.02.002,'first name'"
10 => "S10.G00.02.004,'[email protected]'"
11 => "S10.G00.02.005,'0750000000'"
12 => "S20.G00.05.001,'01'"
13 => "S20.G00.05.002,'01'"
14 => "S20.G00.05.003,'11'"
15 => "S20.G00.05.004,'5'"
16 => "S20.G00.05.010,'01'"
17 => "S10.G00.01.001,'492484944'"
18 => "S10.G00.01.002,'00029'"
19 => "S10.G00.01.003,'Last name'"
]
I would like to select each group of successive lines that start with the same code (the first 10 characters) and put them into an associative array.
The associative array should be like this :
array:5 [▼
0 => array:1 [▼
"S10.G00.00" => array:3 [▼
0 => "S10.G00.00.001,'www.mywebsite.com'"
1 => "S10.G00.00.002,'Company name'"
2 => "S10.G00.00.003,'v2.01'"
]
]
1 => array:1 [▼
"S10.G00.01" => array:5 [▼
0 => "S10.G00.01.001,'492484944'"
1 => "S10.G00.01.002,'00029'"
2 => "S10.G00.01.003,'First name'"
3 => "S10.G00.01.004,'120 R CHARLES'"
4 => "S10.G00.01.005,'92200'"
]
]
2 => array:1 [▼
"S10.G00.02" => array:4 [▼
0 => "S10.G00.02.001,'01'"
1 => "S10.G00.02.002,'first name'"
2 => "S10.G00.02.004,'[email protected]'"
3 => "S10.G00.02.005,'0750000000'"
]
]
3 => array:1 [▼
"S10.G00.05" => array:5 [▼
0 => "S20.G00.05.001,'01'"
1 => "S20.G00.05.002,'01'"
2 => "S20.G00.05.003,'11'"
3 => "S20.G00.05.004,'5'"
4 => "S20.G00.05.010,'01'"
]
]
4 => array:1 [▼
"S10.G00.01" => array:3 [▼
0 => "S10.G00.01.001,'492484944'"
1 => "S10.G00.01.002,'00029'"
2 => "S10.G00.01.003,'Last name'"
]
]
]
All you need is a simple loop and to keep track of the previous 10th characters:
$result = [];
$previousKey = null;
$index = -1;
foreach ($arr as $item) {
$currentKey = substr($item, 0, 10);
if ($previousKey !== $currentKey) {
$previousKey = $currentKey;
$index++;
}
$result[$index][$currentKey][] = $item;
}
demo
When the 10th first characters change, increment the index.
Instead of managing the current group's index in the result array and keeping track of previously encountered values, I prefer to accumulate grouped data in references which are only pushed into the result array once -- when a new group is required. Demo
$result = [];
foreach ($array as $v) {
$prefix = substr($v, 0, 10);
if (!isset($ref[$prefix])) {
unset($ref);
$result[] =& $ref[$prefix];
}
$ref[$prefix][$prefix][] = $v;
}
var_export($result);
Traditionally, I prefer array_reduce()
, to iterate an array and produce a result with a potentially changed array size.
My script requires two static variables, one to manage the first-level index and one to remember the previous group. Demo
print_r(
array_reduce(
$input,
static function ($carry, $item)
{
static $index, $previous;
$group = substr($item, 0, 10);
// increment the index conditionally on a new group
$carry[$index += ($previous && $group !== $previous)]
// memorize the group
[$previous = $group][] = $item;
// push the item
return $carry;
},
[[]]
)
);
If the input array is empty, an array containing a lone empty array will be returned by default.