5

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

For example:

Fist array:

0 => A[1], 1 => B[2], 2 => C[2], 3 => D[2]

Second one,

0 => B[3], 1 => C[4], 2 => E[4], 3 => F[2], 4 => 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.

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,

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

Also, I was about to forget, the whole thing is in PHP.

hakre
  • 178,314
  • 47
  • 389
  • 754
Pierre-Olivier
  • 3,046
  • 16
  • 36
  • 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). – Pierre-Olivier Mar 14 '12 at 17:21

3 Answers3

4

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

Yoshi
  • 51,516
  • 13
  • 81
  • 100
  • 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. – Pierre-Olivier Mar 14 '12 at 17:35
  • 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. – Yoshi Mar 14 '12 at 17:37
  • This version is working perfectly under PHP4. Thank you very much for your help ! Greatly appreciated – Pierre-Olivier Mar 14 '12 at 17:39
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

Felix Kling
  • 705,106
  • 160
  • 1,004
  • 1,072
1

You could use the union operator:

$newArray = $arr1 + $arr2;

You are right, array_merge would only work if your keys were strings. With numeric keys, the second array will just be appended to the first, without overwriting duplicate keys.

bfavaretto
  • 69,385
  • 15
  • 102
  • 145
  • I am getting this result with the union operator: 0 => A[1], 1 => B[2], 2 => C[2], 3 => D[2], 4 => G[2] :( – Pierre-Olivier Mar 14 '12 at 17:28
  • did you try the inverting the order (`$arr2 + $arr1`)? This is how it works: "The + operator returns the right-hand array appended to the left-hand array; for keys that exist in both arrays, the elements from the left-hand array will be used, and the matching elements from the right-hand array will be ignored". – bfavaretto Mar 14 '12 at 17:32
  • @bfavaretto: The keys don't play any role here. It's about the **value** of the entries. This problem does not have a simple solution. – Felix Kling Mar 14 '12 at 17:42