简体   繁体   中英

How to merge 2 array based on value?

I want to combine two arrays into one. Here I have 2 arrays namely remarks and remark_asset .

here are the array of remarks

[
  {
    "id": 5,
    "type": "Text",
    "name": "Text",
    "label": "Txt L",
    "description": "Txt D",
    "filter_logic": null,
    "default": "Txt Def",
    "weight": "12",
    "required": "true",
    "created_at": "2019-12-10 18:20:37",
    "updated_at": "2019-12-10 18:20:37"
  },
  {
    "id": 6,
    "type": "Date",
    "name": "Date",
    "label": "Date Label",
    "description": "Date DEsc",
    "filter_logic": null,
    "default": "2019-12-10",
    "weight": "12",
    "required": "false",
    "created_at": "2019-12-10 18:30:29",
    "updated_at": "2019-12-10 18:30:29"
  },
  {
    "id": 7,
    "type": "Checkbox",
    "name": "Kotaro",
    "label": "Cex",
    "description": "cex desc",
    "filter_logic": null,
    "default": "true",
    "weight": "11",
    "required": "false",
    "created_at": "2019-12-10 18:32:13",
    "updated_at": "2019-12-10 18:32:13"
  },
  {
    "id": 13,
    "type": "List",
    "name": null,
    "label": "Label",
    "description": "Desc",
    "filter_logic": null,
    "default": "1,2,3,4",
    "weight": null,
    "required": "false",
    "created_at": "2019-12-30 01:46:44",
    "updated_at": "2019-12-30 01:46:44"
  }
]

and this is an array of remark assets

[
  [
    {
      "id": 210,
      "asset_id": 94092,
      "remark_id": 5,
      "value": "Txt Def",
      "created_at": "2019-12-13 08:55:41",
      "updated_at": "2019-12-13 08:55:41"
    },
    {
      "id": 211,
      "asset_id": 94092,
      "remark_id": 6,
      "value": "2019-12-10",
      "created_at": "2019-12-13 08:55:41",
      "updated_at": "2019-12-13 08:55:41"
    },
    {
      "id": 212,
      "asset_id": 94092,
      "remark_id": 7,
      "value": "true",
      "created_at": "2019-12-13 08:55:41",
      "updated_at": "2019-12-13 08:55:41"
    }
  ],
  [
    {
      "id": 213,
      "asset_id": 94093,
      "remark_id": 5,
      "value": "Txt Def",
      "created_at": "2019-12-13 09:00:16",
      "updated_at": "2019-12-13 09:00:16"
    },
    {
      "id": 214,
      "asset_id": 94093,
      "remark_id": 6,
      "value": "2019-12-10",
      "created_at": "2019-12-13 09:00:16",
      "updated_at": "2019-12-13 09:00:16"
    },
    {
      "id": 215,
      "asset_id": 94093,
      "remark_id": 7,
      "value": "true",
      "created_at": "2019-12-13 09:00:16",
      "updated_at": "2019-12-13 09:00:16"
    }
  ]
]

And my expectated output is like this:

[
 {
    "Txt L": "Txt Def",
    "Date Label": "2019-12-10",
    "Cex": "true",
    "Label": null
  }
]

Explanation

In the output array, the key of the array is the label of the remarks array. The value of that key is the data of the value key found in the said asset array. The join is made by assets.remarks_id == remarks.id

So the key displayed will be dynamic. How can I merge the two arrays in that way? So the value part must match the id of the remark, for example an asset value is "Txt Def": and that has the same remarks_id as the id where label is "Txt L":

And this is my code :

$getData = $data->get()->take(10);
$remark = Remark::all();
$remarkAsset = RemarkAsset::all();

/* ------------------------------ REMARK ASSET ------------------------------ */
$resultRemarkAsset = array();
foreach ($remarkAsset as $dataRemark) {
    $resultRemarkAsset[$dataRemark['asset_id']][] = $dataRemark;
}
$remarkAssetValue = array_values($resultRemarkAsset); 

//result

You could first create a map (associated array) keyed by the remark id, so you can do a fast look up by that id.

At the same time initialise the result object, so it has all the labels as keys (with null as value)

Then visit all the asset records and find the entry in the above map by remark id. Use the found label to update the result object.

I have named the two input arrays $remarks and $assets :

// Create a map keyed by remark id, and create a template object:
$template = [];
foreach($remarks as $remark) {
    $map[$remark['id']] = $remark;
    $template[$remark['label']] = null;
}

$results = [];
foreach($assets as $assetArray) {
    $result = $template; // copy the template
    // For each asset entry find the label via the map:
    foreach($assetArray as $asset) {
        $id = $asset['remark_id'];
        if (isset($map[$id])) {
            $remark = $map[$id];
            $result[$remark['label']] = $asset['value'];
        }
    }
    $results[] = $result;
}

After this has run, $results will have this content for the sample data you have given:

[{
   "Txt L":"Txt Def",
   "Date Label":"2019-12-10",
   "Cex":"true",
   "Label":null
},{
   "Txt L":"Txt Def",
   "Date Label":"2019-12-10",
   "Cex":"true",
   "Label":null
}]

It has two objects, one for each sub array in the $assets variable. If only one object was expected, then just change the final loop so it puts everything in the same $result object:

$results = [];
$result = $template; // copy the template before the loop
foreach($assets as $assetArray) {
    // For each asset entry find the label via the map:
    foreach($assetArray as $asset) {
        $id = $asset['remark_id'];
        if (isset($map[$id])) {
            $remark = $map[$id];
            $result[$remark['label']] = $asset['value'];
        }
    }
}
$results[] = $result; // There will now only be one entry in the output

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM