Group 1d array of filenames by their leading text and join filenames in each group with a delimiter

33 Views Asked by At

I have a flat array containing filenames. I need to group the filenames by their leading substring and form pipe-delimited elements.

Sample input:

$j = [
    'ma_1_49812_5318.jpg',
    'ma_1_49812_5319.jpg',
    'ma_1_49813_5320.jpg',
    'ma_1_49813_5321.jpg',
];

Desired result:

[
    'ma_1_49812_5318.jpg|ma_1_49812_5319.jpg',
    'ma_1_49813_5320.jpg|ma_1_49813_5321.jpg',
]

My coding attempt:

$entry = array();
$lastjs = '';
$jx ='';
foreach ($j as $group) {
    $jx = explode("_", $group)[2];
    if ($jx == $lastjs || $lastjs == '') {
        $entry[] = $group;
        $lastjs = $jx;
    }
    else
    {
        $entry[] = $group;
        $lastjs = $jx;
    }
}

My incorrect result:

(
    [0] => ma_1_49812_5318.jpg
    [1] => ma_1_49812_5319.jpg
    [2] => ma_1_49813_5320.jpg
    [3] => ma_1_49813_5321.jpg
)
1

There are 1 best solutions below

0
mickmackusa On BEST ANSWER

When you encounter a new real estate property, push a new reference into the result array. When you re-encounter a real estate property, concatenate the reference variable with a pipe then the new value. Using this technique, you do not need to use temporary keys in the result array (this also eliminates the need to call array_values() to re-indes the result array).

Code: (Demo)

$result = [];
foreach ($j as $filename) {
    $groupBy = preg_replace('/_[^_]+$/', '', $filename); // remove unique filename ending
    if (!isset($ref[$groupBy])) {
        $ref[$groupBy] = $filename;
        $result[] = &$ref[$groupBy];
    } else {
        $ref[$groupBy] .= "|$filename";
    }
}
var_export($result);