This question already has answers here:
How to group subarrays by a column value?
(20 answers)
PHP - Group Array by its Sub Array Value (Indexed Array)
(1 answer)
Closed 6 months ago.
i have this array in php json.
i have made it to sort array by first Characther.
but now i'm stuck on how to merge the data under the same title.
my response now is.
[
{
"title": "A",
"data": {
"id": "317",
"name": "Aesethetica"
}
},
{
"title": "A",
"data": {
"id": "318",
"name": "Astonos"
}
},
{
"title": "B",
"data": {
"id": "320",
"name": "Bourjois"
}
},
{
"title": "B",
"data": {
"id": "321",
"name": "Bioderma"
}
}
]
i need to merge all data under each same title.
something like this:
[
{
"title": "A",
"data": [
{
"id": "317",
"name": "Aesethetica"
},
{
"id": "318",
"name": "Astonos"
}
]
},
{
"title": "B",
"data": [
{
"id": "320",
"name": "Bourjois"
},
{
"id": "321",
"name": "Bioderma"
}
]
}
]
kindly help.
Thanks
i got this now:
i made this update.. but still not the needed result.
this is my php code...
$result = [];
foreach ($data as $item) {
$firstLetter = substr($item['name'], 0, 1);
$result[] = [
'title' => $firstLetter = ctype_alnum($firstLetter) ? $firstLetter : '#',
'data' => $item
];
}
foreach ($result as $key => $item) {
$arr[$item['title']][$key] = $item;
}
and this is the result.
{
"A": [
{
"title": "A",
"data": {
"brand_id": "312",
"brand_name": "Adidsa"
}
},
{
"title": "A",
"data": {
"id": "314",
"name": "Adio"
}
},
still can't find make the needed response..
This is not perfomance optimized, but shows a simple solution.
Collect all data grouped by title, then reformat the array to your expected result.
$array = json_decode($json, true);
$collect = [];
foreach($array as $item) {
$collect[$item['title']][] = $item['data'];
}
ksort($collect);
$titles = [];
foreach($collect as $title => $data) {
$names = array_column($data, 'name');
array_multisort($names, SORT_ASC, SORT_STRING, $data);
$titles[] = ['title' => $title, 'data' => $data];
}
echo json_encode($titles, JSON_PRETTY_PRINT); results in
[
{
"title": "A",
"data": [
{
"id": "317",
"name": "Aesethetica"
},
{
"id": "318",
"name": "Astonos"
}
]
},
{
"title": "B",
"data": [
{
"id": "321",
"name": "Bioderma"
},
{
"id": "320",
"name": "Bourjois"
}
]
}
]
Related
I have a array of objects in PHP like:
[
{
"id": 99961,
"candidate": {
"data": {
"id": 125275,
"firstName": "Jose",
"lastName": "Zayas"
}
},
"dateAdded": 1667995574207
},
{
"id": 99960,
"candidate": {
"data": {
"id": 125274,
"firstName": "CHRISTIAN",
"lastName": "NEILS"
}
},
"dateAdded": 1667986477133
},
{
"id": 99959,
"candidate": {
"data": {
"id": 125273,
"firstName": "Jose",
"lastName": "Zayas"
}
},
"dateAdded": 1667985600420
},
{
"id": 99958,
"candidate": {
"data": {
"id": 125275,
"firstName": "Jose",
"lastName": "Zayas"
}
},
"dateAdded": 1667985600420
},
]
I want to find duplicates based on same candidate firstName and lastName but different candidate id's.
I have tried multiple methods like array_search, array_column, array_filter etc but nothing giving desired result.
Output should be array of candidate.data.id that are different but with same firstName and lastName.
Can anyone guide me in building the algorithm?
Group on a key which is composed of the candidate's first name and last name and push the respective id as a child of that group using the id as the key and the value -- this ensures uniqueness within the group.
Then filter out the candidates that only occur once and re-index the qualifying subsets.
Code: (Demo)
$grouped = [];
foreach ($array as $row) {
$compositeKey = "{$row['candidate']['data']['firstName']} {$row['candidate']['data']['lastName']}";
$grouped[$compositeKey][$row['candidate']['data']['id']] = $row['candidate']['data']['id'];
}
$result = [];
foreach ($grouped as $id => $group) {
if (count($group) > 1) {
$result[$id] = array_values($group);
}
}
var_export($result);
Output:
array (
'Jose Zayas' =>
array (
0 => 125275,
1 => 125273,
),
)
Or with one loop, collect all unique ids per group then push all keys into the result array if more than 1 total in the group. (Demo)
$duplicated = [];
foreach ($array as $row) {
$compositeKey = "{$row['candidate']['data']['firstName']} {$row['candidate']['data']['lastName']}";
$id = $row['candidate']['data']['id'];
$grouped[$compositeKey][$id] = '';
if (count($grouped[$compositeKey]) > 1) {
$duplicated[$compositeKey] = array_keys($grouped[$compositeKey]);
}
}
var_export($duplicated);
You need to set iteration for to pick key data (firstName and lastName) for buffer. After it, you can check key from buffer data for to find exists users. :
<?php
$arr = <<<JSON
[
{
"id": 99959,
"candidate": {
"data": {
"id": 125273,
"firstName": "Jose",
"lastName": "Zayas"
}
},
"dateAdded": 1667985600420
},
{
"id": 99961,
"candidate": {
"data": {
"id": 125275,
"firstName": "Jose",
"lastName": "Zayas"
}
},
"dateAdded": 1667995574207
},
{
"id": 99960,
"candidate": {
"data": {
"id": 125274,
"firstName": "CHRISTIAN",
"lastName": "NEILS"
}
},
"dateAdded": 1667986477133
},
{
"id": 99958,
"candidate": {
"data": {
"id": 125275,
"firstName": "Jose",
"lastName": "Zayas"
}
},
"dateAdded": 1667985600420
}
]
JSON;
$candidatePersonality = $exits = [];
$json = json_decode($arr,true);
array_walk($json,function($item,$key) use(&$candidatePersonality,&$exits){
$userKey = $item['candidate']['data']['firstName'].' '.$item['candidate']['data']['lastName'];
if(!isset($candidatePersonality[$userKey]) || (isset($candidatePersonality[$userKey]) && !in_array( $item['candidate']['data']['id'],$candidatePersonality[$userKey]))){
$candidatePersonality[$userKey][] = $item['candidate']['data']['id'];
if(count($candidatePersonality[$userKey])> 1){
$exits[$userKey] = $candidatePersonality[$userKey];
}
}
});
echo '<pre>';
print_r($exits);
I am getting an array from an API that varies in number of levels but follows the same basic structure - here is a truncated sample as this particular repsonse is 25K lines:
{
"Rows": {
"Row": [
{
"Header": {
"ColData": [
{
"value": "Ordinary Income/Expenses"
},
{
"value": ""
}
]
},
"Rows": {
"Row": [
{
"Rows": {},
"Summary": {
"ColData": [
{
"value": "Gross Profit"
},
{
"value": ""
}
]
},
"type": "Section"
},
{
"Header": {
"ColData": [
{
"value": "Income"
},
{
"value": ""
}
]
},
"Rows": {
"Row": [
{
"Header": {
"ColData": [
{
"value": "40000 Sales Income",
"id": "31"
},
{
"value": ""
}
]
},
"Rows": {
"Row": [
{
"Rows": {
"Row": [
{
"ColData": [
{
"value": "2022-01-24"
},
{
"value": "Invoice",
"id": "148774"
},
{
"value": "208232"
},
{
"value": "Hyatt:#211102",
"id": "7568"
},
{
"value": "JN",
"id": "4100000000000368107"
},
{
"value": "CAPTIVE AIRE"
},
{
"value": "11000 Accounts Receivable",
"id": "80"
},
{
"value": "38748.00"
},
{
"value": "38748.00"
}
],
"type": "Data"
},
I need to traverse the json, and where there is data in both [Header][ColData][value] AND [Header][ColData][id] extract the value, id (in this snippet "value": "40000 Sales Income", "id": "31") and the data that immediately follows the "value"/"id" in [Rows][Row][Rows][Row][ColData] (in this snippet starting with "ColData": [{"value": "2022-01-24"...)
[Rows][Row][Rows][Row][ColData] will have one to a few hundred subarrays. I can extract the data from the subarrays once they are found - it's just managing the varying depths of the array that is warping my brain.
[Rows][Row][Rows][Summary] can be discarded as well.
I have tried multiple foreach loops - but by time I get 5 or 6 levels deep it gets very confusing. The number of Header sections varies depending on the report type. The [Rows][Row] nesting is multiple layers deep... I'm sure there has to be a better way than nesting foreach loops...
This is what I've come up with. Kindly modify it to meet your need.
$array = json_decode($json, true);
function traverse_some_array($array){
$result = [];
foreach($array['Rows']['Row'] ?? [] as $row){
if( !empty($row['Header']['ColData']) ){
foreach($row['Header']['ColData'] as $coldata){
if( isset($coldata['value'], $coldata['id']) ){
// there is data in both [Header][ColData][value] AND [Header][ColData][id]
// extract the value, id (in this snippet "value": "40000 Sales Income", "id": "31")
$extract_data = [
'value' => $coldata['value'],
'id' => $coldata['id']
];
// the data that immediately follows the "value"/"id" in [Rows][Row][Rows][Row][ColData]
$immediate_coldata = $row['Rows']['Row'] ?? [];
// you can do what ever you want with the results, eg return it or push it to a result array
$result[] = [
'extract_data' => $extract_data,
'immediate_coldata' => $immediate_coldata
];
}else{
// continue traversing the array
$result = array_merge($result, traverse_some_array($row));
}
}
}
}
return $result;
}
print_r(traverse_some_array($array));
I am new to PHP programming and I need your lights!
I have a JSON file like:
"data": [{
"DIAGNOSTIC_TYPE_ID": 1,
"VALUE": "288.0"
},
{
"DIAGNOSTIC_TYPE_ID": 2,
"VALUE": "-0.1"
},
{
"DIAGNOSTIC_TYPE_ID": 3,
"VALUE": "327.67"
},
{
"DIAGNOSTIC_TYPE_ID": 1,
"VALUE": "288.0"
},
{
"DIAGNOSTIC_TYPE_ID": 2,
"VALUE": "-0.1"
},
{
"DIAGNOSTIC_TYPE_ID": 3,
"VALUE": "327.67"
}]
and I have to change it using another json file which is like:
"diagnostics_keys": [
{
"ID": 1,
"type": "BTTPV",
"key": "0_193_bttpv",
"unit": "V"
},
{
"ID": 2,
"type": "BTTPC",
"key": "0_195_bttpc",
"unit": "A"
},
{
"ID": 3,
"type": "AVGKMKWH",
"key": "0_202_avgkmKwh",
"unit": "Km/Kwh"
}]
How can I combine these two (using the ID and type keys/values of the second json and replace the DIAGNOSTIC_TYPE_ID with those on first json)and take a result like the bellow json?
"data": [{
"DIAGNOSTIC_TYPE_ID": BTTPV,
"VALUE": "288.0"
},
{
"DIAGNOSTIC_TYPE_ID": BTTPC,
"VALUE": "-0.1"
},
{
"DIAGNOSTIC_TYPE_ID": AVGKMKWH,
"VALUE": "327.67"
},
{
"DIAGNOSTIC_TYPE_ID": BTTPV,
"VALUE": "288.0"
},
{
"DIAGNOSTIC_TYPE_ID": BTTPC,
"VALUE": "-0.1"
},
{
"DIAGNOSTIC_TYPE_ID": AVGKMKWH,
"VALUE": "327.67"
}]
Would anyone have any points or links that may know and may help?
//change to arrays
$data = json_decode(YOUR_DATA_JSON, true); // I don't know your json variable names, so replace them
$diagnosticKeys = json_decode(YOUR_DIAGNOSTIC_KEYS_JSON, true);
//iterate over data, this is the one you want to change
foreach ($data as &$dataItem) {//(& is for replacing the values)
//another foreach for diagnostic keys
foreach ($diagnosticKeys as $diagnosticKey) {
if ($dataItem["DIAGNOSTIC_TYPE_ID"] == $diagnosticKey["ID"] {
$dataItem["DIAGNOSTIC_TYPE_ID"] = $diagnosticKey["type"];
}
}
}
//change to json again
$data = json_encode($data);
Not tested but should work.
$data1 = json_decode($json1);
$data2 = json_decode($json2);
$result = [];
foreach ($data1->data as $key => $value) {
foreach($data2->diagnostics_keys as $i => $val){
if($value->DIAGNOSTIC_TYPE_ID==$val->ID){
$value->DIAGNOSTIC_TYPE_ID = $val->type;
$result[$key]['DIAGNOSTIC_TYPE_ID'] = $val->type;
$result[$key]['VALUE'] = $value->VALUE;
}
}
}
echo json_encode($result);
Is there a clean way to combine 2 PHP Arrays conditionally?
I get the following JSON-Response from both arrays separately:
1st Array:
[
{
"field": {
"id": 20,
"name": "Erfolge",
"field-id": "erfolge",
"type": "textarea"
}
},
{
"field": {
"id": 29,
"name": "Sprachen",
"field-id": "sprachen",
"type": "text"
}
}
]
2nd Array:
[
{
"field": {
"id": 20,
"name": "Erfolge",
"field-id": "erfolge",
"type": "textarea"
},
"value": "new entry"
},
{
"field": {
"id": 4,
"name": "Trikotnummer",
"field-id": "trikotnummer",
"type": "number"
},
"value": "test"
},
{
"field": {
"id": 29,
"name": "Sprachen",
"field-id": "sprachen",
"type": "text"
},
"value": "Text"
}
]
I want the following target output:
[
{
"field": {
"id": 20,
"name": "Erfolge",
"field-id": "erfolge",
"type": "textarea"
},
value: "new entry"
},
{
"field": {
"id": 29,
"name": "Sprachen",
"field-id": "sprachen",
"type": "text"
},
value: "Text"
}
]
That means it must only add the values if the field exists in the 1st array.
My current solution gives me all the fields without the correct mapping:
$fieldData = array();
foreach ($fields as $field) {
$fieldData[]['fields'] = $field->getArrayCopy();
}
// Get Values
$values = $user->getProfileFieldValue();
$fieldValue = array();
foreach ($values as $value) {
$fieldValue[] = $value->getArrayCopy();
}
$result = array_merge($fieldData, $fieldValue);
Should I use the function array_walk?
This is an expensive way to do it, it searches the second array looking for the element matching the ID from the first array.
$result = array();
foreach ($first as $e1) {
$id = $e1['field']['id'];
foreach ($secondArray as $e2) {
if ($e2['field']['id'] == $id) {
$e1['value'] = $e2['value'];
break;
}
}
$result[] = $e1;
}
If the second array is very large, you can optimize it by first creating an associative array whose key are the IDs from the second array and values are the values.
https://secure.php.net/manual/en/function.array-uintersect.php
$res = array_uintersect($arr1, $arr2, function($a, $b){
return $a['field']['id'] - $b['field']['id'];
});
For 2 days, I'm trying to extract informations from a multidimensional array and I think I'm stuck after trying a lot of things
Here is my json
{
"profile": [
{
"id": "123456",
"hostId": null,
"description": [
{
"id": "name",
"value": "foo"
},
{
"id": "name2",
"value": "foo2"
},
{
"id": "bio",
"value": "heyyyy"
},
{
"id": "location",
"value": "somewhere"
}
],
"ishere": true
}
]
}
I want to manipulate it to have this
{
"id": "123456",
"host": null,
"name": "foo",
"name2": "foo2",
"bio": "heyyyy",
"location": "somewhere",
"ishere": true
}
with this (after a json_decode)
foreach ($array->profileUsers[0]->settings as $item) {
$out2[$item->id] = $item->value;
}
I only have
{
"name": "foo",
"name2": "foo2",
"bio": "heyyyy",
"location": "somewhere"
}
Thank you
This should do the trick:
$obj = json_decode($your_json);
$obj = $obj->profile[0];
foreach($obj->description as $d)
$obj->{$d->id} = $d->value;
unset($obj->description);
$data = json_decode($your_json, true);
$new_array = [];
foreach($data['profile'] as $key=>$item) {
if(is_array($item)) {
$new_array[$item['id']] = $item['value'];
}
else {
$new_array[$key] = $item;
}
}
Hardcoded this, hope it will help.