5

I would like to merge two arrays containing a list of files plus their revision in brackets.

For example:

First array:

['A[1]', 'B[2]', 'C[2]', 'D[2]']

Second one:

['B[3]', 'C[4]', 'E[4]', 'F[2]', 'G[2]']

Like I said, I would be able to merge both arrays, but overwriting the first one by the data present in the second one where the letter/filenames collide.

I used this regex to only grab filenames (removing the revision number). I don't know if I am correct on this point:

/\[[^\)]+\]/

The result I am looking for would be this,

['A[1]', 'B[3]', 'C[4]', 'D[2]', 'E[4]', 'F[2]', 'G[2]']

I'm using PHP4 at the moment.

1
  • 1
    array_merge won't work in my case because I need to overwrite existing data. Also, I need to deal with revisions numbers associated with the files (in one big string). Commented Mar 14, 2012 at 17:21

3 Answers 3

3

something like:

function helper() {
  $result = array();

  foreach (func_get_args() as $fileList) {
    foreach ($fileList as $fileName) {
      list($file, $revision) = explode('[', $fileName, 2);
      $revision = trim($revision, ']');
      $result[$file] = !isset($result[$file]) ? $revision : max($result[$file], $revision);
    }
  }

  foreach ($result as $file => $revision) {
    $result[$file] = sprintf('%s[%s]', $file, $revision);
  }

  return array_values($result);
}

$a = array('A[1]', 'B[2]', 'C[2]', 'D[2]');
$b = array('B[3]', 'C[4]', 'E[4]', 'F[2]', 'G[2]');

print_r(helper($a, $b));

demo: http://codepad.org/wUMMjGXC

Sign up to request clarification or add additional context in comments.

3 Comments

The previous code you posted was working flawlessly ! I forgot to mention, but we are still using PHP4 here :( But thanks for your answer, it is working perfectly.
Changed it again (a bit). I guess it should work in php4 too. The func_get_args() part could be problematic. Could be that you have to use an extra variable instead of using the result directly.
This version is working perfectly under PHP4. Thank you very much for your help ! Greatly appreciated
2

One way would be to map both arrays to

filename => filename[revision]

such that

Array
(
    [0] => A[1]
    [1] => B[2]
    [2] => C[2]
    [3] => D[2]
)

becomes

Array
(
    [A] => A[1]
    [B] => B[2]
    [C] => C[2]
    [D] => D[2]
)

and then use array_merge (which overrides entries with the same key).

Something like:

function map($array) {
    $filenames = array_map(function($value) {
        return strstr($value, '[', false);
    }, $array);
    return array_combine($filenames, $array);
}

$result = array_merge(map($array1), map($array2));

If you want to have numeric indexes, you can call array_values on the result. The code above requires PHP 5.3 but it should be easy to make it compatible with earlier versions. The other caveat is that it would only work if filenames are unique in the array.

DEMO (PHP 5.2 version)

Reference: array_map, strstr, array_combine, array_merge

2 Comments

Thank you very much for your answer, but I forgot to mention that we are still using PHP4 here :(
Yeah I noticed that :D I will still leave the answer for others not using PHP 4 ;)
0

Simply iterate over each array and assign temporary keys while pushing values into the result array. Iterate the arrays in order so that the second array's values overwrite the first array's values. When finished looping, you can discard the temporary/grouping keys by calling array_values().

Code: (Demo)

$a = ['A[1]', 'B[2]', 'C[2]', 'D[2]'];
$b = ['B[3]', 'C[4]', 'E[4]', 'F[2]', 'G[2]'];

$result = [];
foreach ($a as $v) {
    $result[strtok($v, '[')] = $v;
}
foreach ($b as $v) {
    $result[strtok($v, '[')] = $v;
}
var_export(array_values($result));

Output:

array (
  0 => 'A[1]',
  1 => 'B[3]',
  2 => 'C[4]',
  3 => 'D[2]',
  4 => 'E[4]',
  5 => 'F[2]',
  6 => 'G[2]',
)

Because your input arrays are logically unique in their grouping letter, this functional-style snippet will provide the same result as the above script: (Demo)

var_export(
    array_values(
        array_reduce(
            array_merge($a, $b),
            function($result, $v) {
                $result[strtok($v, '[')] = $v;
                return $result;
            }
        )
    )
);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.