Home > Net >  Merge rows from 2 arrays by grouping on shared column value
Merge rows from 2 arrays by grouping on shared column value

Time:08-16

I have 2 arrays that i need to merge in PHP. (samples below) I have tried nested foreach with if statements that sort of work, but it isn't very clean and also fails under certain conditions -- such as if both arrays have the same number of items, but the meterid's don't match.

$startArr

[
    {
        "meterid": 23484,
        "expired_total": 1
    },
    {
        "meterid": 23489,
        "expired_total": 3
    }
]

$expArr

[
    {
        "meterid": 23478,
        "start_total": 1
    },
    {
        "meterid": 23489,
        "start_total": 1
    },
    {
        "meterid": 23490,
        "start_total": 2
    }
]

$output_result

{
    "23478": {
        "meterid": 23478,
        "start_total": 1,
        "expired_total": 0
    },
    "23484": {
        "meterid": 23484,
        "start_total": 0,
        "expired_total": 1
    }
    "23489": {
        "meterid": 23489,
        "start_total": 1,
        "expired_total": 3
    }
    "23490": {
        "meterid": 23490,
        "start_total": 2,
        "expired_total": 0
    }
}

My code:

$output_result = [];
if (count($startArr) >= count($expArr)) {
    foreach ($startArr as $start_val) {
        $meterid = $start_val['meterid'];
        foreach ($expArr as $exp_val) {
            if ($meterid == $exp_val['meterid']) {
                $output_result[$meterid] = array("meterid" => $meterid, "start_total" => $start_val['start_total'], "expired_total" => $exp_val['expired_total']);
                break;
            } else {
                $output_result[$meterid] = array("meterid" => $meterid, "start_total" => $start_val['start_total'], "expired_total" => 0);
            }
        }
    }
} else {
    foreach ($expArr as $exp_val) {
        $meterid = $exp_val['meterid'];
        foreach ($startArr as $start_val) {
            if ($meterid == $exp_val['meterid']) {
                $output_result[$meterid] = array("meterid" => $meterid, "start_total" => $start_val['start_total'], "expired_total" => $exp_val['expired_total']);
                break;
            } else {
                $output_result[$meterid] = array("meterid" => $meterid, "start_total" => 0, "expired_total" => $exp_val['expired_total']);
            }
        }
    }
}
echo json_encode($output_result);

CodePudding user response:

  1. Merge and iterate the rows.
  2. Determine groups by declaring associative first level keys using the meterid values.
  3. When a group is newly encountered, store the row with the missing element defaulted to 0.
  4. If a group is encountered more than once, just overwrite the stored group values with the new values.

Code: (Demo)

$result = [];
$default = array_fill_keys(['meterid', 'start_total', 'expired_total'], 0);
foreach (array_merge($startArr, $expArr) as $row) {
    if (!isset($result[$row['meterid']])) {
        $result[$row['meterid']] = array_replace($default, $row);
    } else {
        $result[$row['meterid']]  = $row;
    }
}
var_export($result);

More compact version of the above: (Demo)

$result = [];
$default = array_fill_keys(['meterid', 'start_total', 'expired_total'], 0);
foreach (array_merge($startArr, $expArr) as $row) {
    $result[$row['meterid']] = array_replace($result[$row['meterid']] ?? $default, $row);
}
var_export($result);
  • Related