PHP to split array of objects with title in array - php

I have an array of objects like below:
[
{
"TYPE": "food",
"NAME": "abc"
},
{
"TYPE": "fruit",
"NAME": "xyz"
},
{
"TYPE": "food",
"NAME": "def"
},
{
"TYPE": "food",
"NAME": "ghi"
},
]
How can I split this array of objects into multiple arrays such that the desired output looks like:
[
{
"TYPE": "food",
"ITEMS":
[
{
"TYPE": "food",
"NAME": "abc"
},
{
"TYPE": "food",
"NAME": "def"
},
{
"TYPE": "food",
"NAME": "ghi"
},
]
},
{
"TYPE": "fruit",
"ITEMS":
[
{
"TYPE": "fruit",
"NAME": "xyz"
},
]
},
]
Note that the parent object has its own identifier (TYPE)
I tried this:
$result = [];
foreach ($DT_DATA as $key => $value) {
$group = $value->TYPE;
if (!isset($result[$group])) {
$result[$group] = [];
}
$result[$group][] = $value;
}
$result = array_values($result);
But the parent group does not contain "TYPE" and also "ITEMS" array

Some improvements that will do the job:
$result = [];
foreach ($DT_DATA as $key => $value) {
$group = $value->TYPE;
if (!isset($result[$group])) {
// init with array of required structure
$result[$group] = [
'TYPE' => $group,
'ITEMS' => [],
];
}
// add $value to `ITEMS` subarray
$result[$group]['ITEMS'][] = $value;
}
$result = array_values($result);

Related

Find duplicates from array of objects in php

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);

merge all arrays with same title [duplicate]

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"
}
]
}
]

Parsing an array with PHP in a foreach loop

I want to parse an array with PHP's foreach loop to get the object names and values inside the 'ques' array.
[
{
"ques": [
{
"name": "comment",
"value": "comment me for the reason",
"sur_id": "1",
"user_id": "admin#gmail.com",
"pagename": "question_response"
},
{
"name": "check-box[]",
"value": "1"
},
{
"name": "radio",
"value": "radio 2"
},
{
"name": "yes",
"value": "no"
}
]
"ques":[
{
"name": "date",
"value": "2015-10-23"
},
{
"name": "select-deopdown",
"value": ""
},
{
"name": "true",
"value": "false"
},
{
"name": "number",
"value": "55"
}
]
}
]
I want to separate the value from the 'ques' array:
while ($fetch = mysql_fetch_array($query1)) {
$content = $fetch['CONTENT_VALUES'];
// print_r($content);
$content_value= mb_convert_encoding($content ,"UTF-8");
$datas = json_decode($content, true);
foreach($datas->ques as $values)
{
echo $values->value . "\n";
print_r($values);
}
$test[] = array('ques' => $datas ,'answer'=>$values);
}

Conditionally Combine PHP Array

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'];
});

PHP - Nested array keys based on string lines

I need a help. I'm looking for a solution for this problem!
I have a file which contains the following pattern:
Brazil|SaoPaulo|Diadema|RuadaFe Brazil|SaoPaulo|Diadema|RuadoLimoeiro
Brazil|SaoPaulo|SaoCaetano|RuadasLaranjeiras
Brazil|Parana|Curitiba|ComendadorAraujo
USA|NewJersey|JerseyCity|WhashingtonBoulervard
USA|NewJersey|JerseyCity|RiverCourt
Which should bring after some array key implementation, something like this (after apply json_encode call on php):
{
"name": "Brazil",
"children": [
{
"name": "SaoPaulo",
"children": [
{
"name": "Diadema",
"children": [
{"name": "RuadaFe"},
{"name": "RuadoLimoeiro"}
]
},
{
"name": "SaoCaetano",
"children": [
{"name": "RuadasLaranjeiras"}
]
},
]
"name": "Parana",
"children": [
{
"name": "Curitiba",
"children": [
{"name": "ComendadorAraujo"}
]
}
]
},
"name":"USA",
"children":[
{
"name": "NewJersey",
"children": [
{
"name": "JerseyCity",
"children": [
{"name": "WhashingonBoulevard"},
{"name": "RiverCourt"}
]
}
]
}
]
}
]
And keep going and going (and even more deeper too).
Please, help me team... thanks in advance.
Here what I get until now:
Array
(
[Brazil] => Array
(
[SaoPaulo] => Array
(
[Diadema] => Array
(
[RuadoLimoeiro] =>
)
[SaoCaetano] => Array
(
[RuadasLaranjeiras] =>
)
)
[Parana] => Array
(
[Curitiba] => Array
(
[ComendadorAraujo] =>
)
)
)
[USA] => Array
(
[NewJersey] => Array
(
[JerseyCity] => Array
(
[WhashingtonBoulervard] =>
[RiverCourt] =>
)
)
)
)
And here is the json encoded:
{
"Brazil":{
"SaoPaulo":
{"Diadema":
{"RuadoLimoeiro":null},
"SaoCaetano":{"RuadasLaranjeiras":null}
},
"Parana":
{"Curitiba":
{"ComendadorAraujo":null}
}
},
"USA":{
"NewJersey":{
"JerseyCity":{
"WhashingtonBoulervard":null,
"RiverCourt":null}
}
}
}
As you can see, the "names" and "child" is missing because is not an array key structure, also something is wrong, because I'm missing some values on SaoPaulo.
Here is the function:
foreach($strings as $string) {
$parts = array_filter(explode('|', $string));
$ref = &$result;
foreach($parts as $p) {
// echo $p;
if(!isset($ref[$p])) {
$ref[$p] = array();
// $ref[$p] = array("name"=>$p);
}
$ref = &$ref[$p];
}
$ref = null;
}
-------------------------------- AFTER SOME ANSWERS --------------------------
{
"name": "Brazil(country)",
"children": [
{
"name": "SaoPaulo(state)", // only one state
"children": [
{
"name": "Diadema(city)", // only one city
"children": [
{"name": "RuadaFe(street)"}, // two streets under the same city...
{"name": "RuadoLimoeiro(street)"}
]
},
{
"name": "SaoCaetano(city)",
"children": [
{"name": "RuadasLaranjeiras(street)"}
]
},
]
"name": "Parana(state)",
"children": [
{
"name": "Curitiba(city)",
"children": [
{"name": "ComendadorAraujo(street)"}
]
}
]
},...
I put on parentesis the structure (country, state, city, street) just to clarify what i want.
Got it?
It is not outright trivial, but what I did is actually the same as you (the same way as in your edited question), but I also keep track of those arrays to rename the keys. And that's what I do afterwards then:
$separator = [' ', '|'];
$buffer = file_get_contents($file);
$entries = explode($separator[0], $buffer);
$result = [];
$named[] = &$result;
########
foreach ($entries as $entry) {
$each = explode($separator[1], $entry);
$pointer = & $result;
while ($current = array_shift($each)) {
if (!isset($pointer[$current])) {
unset($children);
$children = [];
$named[] = &$children;
########
$pointer[$current] = ['name' => $current, 'children' => &$children];
}
$pointer = & $pointer[$current]['children'];
}
}
foreach($named as $offset => $namedArray) {
$keys = array_keys($namedArray);
foreach($keys as $key) {
$named[$offset][] = &$namedArray[$key];
unset($named[$offset][$key]);
}
}
print_r($result);
See it in action.
You probably might want to modify this by checking in the later foreach if children are empty (leaf-nodes) and then removing the children entry as well.
Here the modified foreach at the end and json output:
foreach($named as $offset => $namedArray) {
$keys = array_keys($namedArray);
foreach($keys as $key) {
if (!$namedArray[$key]['children']) {
unset($namedArray[$key]['children']);
}
$named[$offset][] = &$namedArray[$key];
unset($named[$offset][$key]);
}
}
echo json_encode($result, JSON_PRETTY_PRINT);
Output:
[
{
"name": "Brazil",
"children": [
{
"name": "SaoPaulo",
"children": [
{
"name": "Diadema",
"children": [
{
"name": "RuadaFe"
},
{
"name": "RuadoLimoeiro"
}
]
},
{
"name": "SaoCaetano",
"children": [
{
"name": "RuadasLaranjeiras"
}
]
}
]
},
{
"name": "Parana",
"children": [
{
"name": "Curitiba",
"children": [
{
"name": "ComendadorAraujo"
}
]
}
]
}
]
},
{
"name": "USA",
"children": [
{
"name": "NewJersey",
"children": [
{
"name": "JerseyCity",
"children": [
{
"name": "WhashingtonBoulervard"
},
{
"name": "RiverCourt"
}
]
}
]
}
]
}
]
The full code-example at a glance:
<?php
/**
* PHP - Nested array keys based on string lines
* #link http://stackoverflow.com/a/16305236/2261774
*/
$file = 'data://text/plain;base64,' . base64_encode('Brazil|SaoPaulo|Diadema|RuadaFe Brazil|SaoPaulo|Diadema|RuadoLimoeiro Brazil|SaoPaulo|SaoCaetano|RuadasLaranjeiras Brazil|Parana|Curitiba|ComendadorAraujo USA|NewJersey|JerseyCity|WhashingtonBoulervard USA|NewJersey|JerseyCity|RiverCourt');
$separator = [' ', '|'];
$buffer = file_get_contents($file);
$entries = explode($separator[0], $buffer);
$result = [];
$named[] = &$result;
foreach ($entries as $entry) {
$each = explode($separator[1], $entry);
$pointer = & $result;
while ($current = array_shift($each)) {
if (!isset($pointer[$current])) {
unset($children);
$children = [];
$named[] = &$children;
$pointer[$current] = ['name' => $current, 'children' => &$children];
}
$pointer = & $pointer[$current]['children'];
}
}
unset($pointer);
foreach($named as $offset => $namedArray) {
$keys = array_keys($namedArray);
foreach($keys as $key) {
if (!$namedArray[$key]['children']) {
unset($namedArray[$key]['children']);
}
$named[$offset][] = &$namedArray[$key];
unset($named[$offset][$key]);
}
}
unset($named);
echo json_encode($result, JSON_PRETTY_PRINT);
your question JSON:
{
"name": "Brazil",
"children": [
{
"name": "SaoPaulo",
"children": [
{
"name": "Diadema",
"children": [
{"name": "RuadaFe"},
{"name": "RuadoLimoeiro"}
]
},
My Answer JSON:
[
{
"name": "Brazil",
"children": [
{
"name": "SaoPaulo",
"children": [
{
"name": "Diadema",
"children": [
{
"name": "RuadaFe"
},
{
"name": "RuadoLimoeiro"
}
]
},
The only difference I can spot is that the root-nodes are wrapped inside an array in my answer, but it should be trivial to fetch them out there if that really is your issue ;)
Does it solves your problem? Use $inputString to put your real string.
<?php
// ------------------------------------------------------ your input goes here ------------------------------------------------------
$inputString = 'Brazil|SaoPaulo|Diadema|RuadaFe Brazil|SaoPaulo|Diadema|RuadoLimoeiro Brazil|SaoPaulo|SaoCaetano|RuadasLaranjeiras Brazil|Parana|Curitiba|ComendadorAraujo USA|NewJersey|JerseyCity|WhashingtonBoulervard USA|NewJersey|JerseyCity|RiverCourt';
class item {
public $name = null;
public function getChildrenByName($strName) {
$ret = null;
# this variable should be defined in interface, but i skipped it so it wont be printed in json when obj does not have childrens
if( !isset( $this->children ) ) {
$this->children = array( );
}
foreach ( $this->children as $child ) {
if( $child->name === $strName ) {
$ret = $child;
break;
}
}
if ( !$ret ) {
$this->children[] = self::spawnByName( $strName );
}
return $this->children[ count($this->children) - 1];
}
static public function spawnByName($strName) {
$ret = new item();
$ret->name = $strName;
return $ret;
}
}
class listManager {
protected $list = array();
public function getList() {
return $this->list;
}
public function addPath( $desiredPath ) {
# path needs to be as array
if ( is_string( $desiredPath ) ) {
$desiredPath = explode('|', $desiredPath);
}
# create root element if it does not already exists
if ( !isset( $this->list[$desiredPath[0]] ) ) {
$this->list[$desiredPath[0]] = item::spawnByName($desiredPath[0]);
}
$curElement = $this->list[$desiredPath[0]];
for( $i=1; $i<count($desiredPath); $i++ ) {
$curElement = $curElement->getChildrenByName( $desiredPath[$i] );
}
}
protected function spawnElement( $strName ) {
$ret = new item();
$ret->name = $strName;
return $ret;
}
}
$output = array();
$expl = explode(' ', $inputString);
$list = new listManager();
foreach ( $expl as $key => $path ) {
$list->addPath( $path );
}
$output = '';
foreach ( $list->getList() as $singleVariable ) {
$output .= json_encode($singleVariable, JSON_PRETTY_PRINT) . ",\n";
}
echo '<pre>'.$output.'</pre>';
?>
Above code produces following json out of your sample code:
{
"name": "Brazil",
"children": [{
"name": "SaoPaulo",
"children": [{
"name": "Diadema",
"children": [{
"name": "RuadaFe"
}
]
}
]
}, {
"name": "SaoPaulo",
"children": [{
"name": "Diadema",
"children": [{
"name": "RuadoLimoeiro"
}
]
}
]
}, {
"name": "SaoPaulo",
"children": [{
"name": "SaoCaetano",
"children": [{
"name": "RuadasLaranjeiras"
}
]
}
]
}, {
"name": "Parana",
"children": [{
"name": "Curitiba",
"children": [{
"name": "ComendadorAraujo"
}
]
}
]
}
]
} {
"name": "USA",
"children": [{
"name": "NewJersey",
"children": [{
"name": "JerseyCity",
"children": [{
"name": "WhashingtonBoulervard"
}
]
}
]
}, {
"name": "NewJersey",
"children": [{
"name": "JerseyCity",
"children": [{
"name": "RiverCourt"
}
]
}
]
}
]
}
edit: changed, does it fit now?

Categories