0

I have the following issue that seems common but can't figure out which array function might work for the following format:

(Already tried array_merge , array_merge_recursive , array_combine, array_splice but didn't work as expected.)

Array
(
    [0] => Array
        (
            [r_id] => 11
            [r_sid] => RC
            [d_id] => 2
        )

    [1] => Array
        (
            [r_id] => 7
            [r_sid] => RC
            [c_id] => 51
        )

    [2] => Array
        (
            [r_id] => 6
            [r_sid] => JN
            [c_id] => 52
        )

    [3] => Array
        (
            [r_id] => 7
            [r_sid] => JN
            [c_id] => 51
        )

    [4] => Array
        (
            [r_id] => 7
            [r_sid] => LG
            [c_id] => 51
        )

    [5] => Array
        (
            [r_id] => 7
            [r_sid] => BN
            [c_id] => 51
        )

    [6] => Array
        (
            [r_id] => 6
            [r_sid] => IVS
            [c_id] => 52
        )

    [7] => Array
        (
            [r_id] => 7
            [r_sid] => IVS
            [c_id] => 51
        )

)

Now, I need to merge this array values by common r_sid & c_id keys; The only special case scenario is if there is a d_id key instead of c_id then we merge/combine that with any value in the array that has similar r_sid.

The final solution needs to look like this, if thats easier to understand:

Array
(
    [0] => Array
        (
            [r_id] => 11,7
            [r_sid] => RC
            [d_id] => 2
            [c_id] => 51 
        )


    [1] => Array
        (
            [r_id] => 6,7
            [r_sid] => JN, IVS
            [c_id] => 52,51
        )

)

The r_sid values that do not match with anyone needs to be discarded.

Any help is appreciated. Many thanks!

Unheilig
  • 16,196
  • 193
  • 68
  • 98
  • There isn't a specific function to cope with the various combinations you want, you will need to write something yourself. – Nigel Ren Apr 19 '20 at 06:00
  • How do you decide not to merge all the values with `c_id = 51` or `c_id = 52` together? – Nick Apr 19 '20 at 06:03
  • It’s only d_id that takes precedence and , is present in one or two values. So, if present it will need to find other values which match r_sid. Otherwise it’s always c_id that this array is filled with. – user7616631 Apr 19 '20 at 06:12
  • @nigel ren: I do understand that it’s a bit more specific but I have been writing my own sub functions do far to finally come to this array. Just can’t work out this last matching. – user7616631 Apr 19 '20 at 06:13
  • Can you add the code you have so far to the question as it may be easier to complete that than do something completely new (although that may also be suggested). – Nigel Ren Apr 19 '20 at 06:16
  • @Nick, one way I thought it can be done is to merge all r_sid common values and make other keys comma separated. If there is an additional d_id, then we combine and keep both keys d_id and c_id and append r_id, r_sid values atleast. – user7616631 Apr 19 '20 at 06:16
  • I don't really understand why you would want to do this merging, but regardless, unless you can come up with a good description of how the decision to merge different `r_sid` and `c_id` values is made I don't think it's possible to answer the question. I cannot see how you decided to merge the values in the second element in your output array. – Nick Apr 19 '20 at 06:19
  • Merging needs to happen based on common r_sid values. Any array with r_sid value not repeated throughout needs to be discarded. Does that now make sense? My code unfortunately has a lot of confidential data so can’t paste it all here but that’s the final array left out to be worked. – user7616631 Apr 19 '20 at 06:23
  • That still doesn't explain why you merged the two arrays with `r_sid = JN` and `r_sid = IVS`. Those are different `r_sid` values, not common. – Nick Apr 19 '20 at 06:36

1 Answers1

0

Here's a piece of code that is my best interpretation of how to merge your array:

// filter out r_sid values which only occur once
$sid_values = array_count_values(array_column($array, 'r_sid'));
$array = array_filter($array, function ($a) use ($sid_values) { return $sid_values[$a['r_sid']] > 1; });

// combine arrays on r_sid values
$result = array();
foreach ($array as $arr) {
    $sid = $arr['r_sid'];
    // push data to arrays
    $result[$sid]['r_sid'] = $sid;
    $result[$sid]['r_id'][] = $arr['r_id'];
    if (isset($arr['c_id'])) $result[$sid]['c_id'][] = $arr['c_id'];
    if (isset($arr['d_id'])) $result[$sid]['d_id'][] = $arr['d_id'];
}

// combine all the c_id values into a string
array_walk($result, function (&$a) {
    if (isset($a['c_id'])) $a['c_id'] = implode(',', $a['c_id']);
});

// now combine any r_sid values that have the same set of c_id values
$output = array();
foreach ($result as $res) {
    $cid = $res['c_id'];
    // push data to arrays
    $output[$cid]['c_id'] = $cid;
    $output[$cid]['r_sid'] = array_merge($output[$cid]['r_sid'] ?? array(), array($res['r_sid']));
    $output[$cid]['r_id'] = array_merge($output[$cid]['r_id'] ?? array(), $res['r_id']);
    if (isset($res['d_id'])) $output[$cid]['d_id'] = array_merge($output[$cid]['d_id'] ?? array(), $res['d_id']);
}

// combine the r_sid, r_id and d_id values into a string
array_walk($output, function (&$a) {
    $a['r_sid'] = implode(',', $a['r_sid']);
    $a['r_id'] = implode(',', array_unique($a['r_id']));
    if (isset($a['d_id'])) $a['d_id'] = implode(',', $a['d_id']);
});

// remove the associative keys
$output = array_values($output);

Output:

Array
(
    [0] => Array
        (
            [c_id] => 51
            [r_sid] => RC
            [r_id] => 11,7
            [d_id] => 2
        )
    [1] => Array
        (
            [c_id] => 52,51
            [r_sid] => JN,IVS
            [r_id] => 6,7
        )
)

Demo on 3v4l.org

Nick
  • 138,499
  • 22
  • 57
  • 95
  • @user7616631 no worries. But... it works for the very small example you've given. I don't know how well it will go when you try it on some serious data... – Nick Apr 20 '20 at 10:05