I am trying to sort json object by same key and merge the value part using PHP but not getting the result as expected. My code is below:
$customArr=[{"attribute_code":"budget","value":"141"},{"attribute_code":"restaurants","value":"166"},{"attribute_code":"food_type","value":"172"},{"attribute_code":"budget","value":"142"},{"attribute_code":"restaurants","value":"168"},{"attribute_code":"food_type","value":"173"},{"attribute_code":"budget","value":"143"},{"attribute_code":"restaurants","value":"170"},{"attribute_code":"food_type","value":"173"},{"attribute_code":"budget","value":"162"},{"attribute_code":"restaurants","value":"171"},{"attribute_code":"food_type","value":"172"}]
function sortByName($a, $b){
$a = $a['attribute_code'];
$b = $b['attribute_code'];
if ($a == $b) return 0;
return ($a < $b) ? -1 : 1;
}
usort($customArr, 'sortByName');
Here I need if attribute_code is same then push the respective value into one array and also the duplicate value should not be there. The expected result is given below.
[{"attribute_code":"budget","value":[141,142,143,162]},{}.....]
But in my case the expected result not coming.
Using array_reduce() you can try it. array_reduce() callback takes two arguments, who's first argument is the old/previous iteration value and second argument is the current iteration value/element.
So using this function we can holds our current iteration values to the previous iteration value (total values).
array_reduce() iteratively reduce the array to a single value using a callback function.
$customArr = json_decode('[{"attribute_code":"budget","value":"141"},{"attribute_code":"restaurants","value":"166"},{"attribute_code":"food_type","value":"172"},{"attribute_code":"budget","value":"142"},{"attribute_code":"restaurants","value":"168"},{"attribute_code":"food_type","value":"173"},{"attribute_code":"budget","value":"143"},{"attribute_code":"restaurants","value":"170"},{"attribute_code":"food_type","value":"173"},{"attribute_code":"budget","value":"162"},{"attribute_code":"restaurants","value":"171"},{"attribute_code":"food_type","value":"172"}]', true);
$data = array_reduce($customArr, function ($acc, $new) {
if (isset($acc[$new['attribute_code']])) {
$old_value = $acc[$new['attribute_code']]['value'];
$acc[$new['attribute_code']]['value'] = array_unique(is_array($old_value) ? array_merge($old_value, [$new['value']]) : [$old_value, $new['value']]);
} else {
$acc[$new['attribute_code']] = $new;
}
return $acc;
}, []);
ksort($data);
echo '<pre>', json_encode(array_values($data));
Working demo.
At the moment you are just sorting the entries according to the attribute_code and doing nothing about merging the data items.
This code creates a new output array (keyed it by the attribute_code), if the code is already there it adds the value into the list of existing values, if not it adds a new item in, creating the value as an array (with the first item in). Lastly it uses ksort() to sort the items.
If you don't need these keys, then array_values() will give you a plain array (as in the output)...
$json='[{"attribute_code":"budget","value":"141"},{"attribute_code":"restaurants","value":"166"},{"attribute_code":"food_type","value":"172"},{"attribute_code":"budget","value":"142"},{"attribute_code":"restaurants","value":"168"},{"attribute_code":"food_type","value":"173"},{"attribute_code":"budget","value":"143"},{"attribute_code":"restaurants","value":"170"},{"attribute_code":"food_type","value":"173"},{"attribute_code":"budget","value":"162"},{"attribute_code":"restaurants","value":"171"},{"attribute_code":"food_type","value":"172"}]';
$customArr = json_decode($json, true);
$output = [];
foreach ( $customArr as $attribute ) {
if ( isset ( $output[$attribute['attribute_code']])) {
$output[$attribute['attribute_code']]['value'][] = $attribute['value'];
}
else {
$output[$attribute['attribute_code']] = ["attribute_code"=>$attribute['attribute_code'],
"value"=> [$attribute['value']]];
}
}
// Make sure values are unique
foreach ( $output as $code => $value ){
$output[$code]['value'] = array_unique($output[$code]['value']);
}
ksort($output);
print_r(array_values($output));
gives...
Array
(
[0] => Array
(
[attribute_code] => budget
[value] => Array
(
[0] => 141
[1] => 142
[2] => 143
[3] => 162
)
)
[1] => Array
(
[attribute_code] => food_type
[value] => Array
(
[0] => 172
[1] => 173
)
)
[2] => Array
(
[attribute_code] => restaurants
[value] => Array
(
[0] => 166
[1] => 168
[2] => 170
[3] => 171
)
)
)
You have a JSON string, not an array.
$jsonString = '[{"attribute_code":"budget","value":"141"},{"attribute_code":"restaurants","value":"166"},{"attribute_code":"food_type","value":"172"},{"attribute_code":"budget","value":"142"},{"attribute_code":"restaurants","value":"168"},{"attribute_code":"food_type","value":"173"},{"attribute_code":"budget","value":"143"},{"attribute_code":"restaurants","value":"170"},{"attribute_code":"food_type","value":"173"},{"attribute_code":"budget","value":"162"},{"attribute_code":"restaurants","value":"171"},{"attribute_code":"food_type","value":"172"}]';
$customArr = json_decode($jsonString, true);
function sortByName($a, $b)
{
$a = $a['attribute_code'];
$b = $b['attribute_code'];
if ($a == $b) return 0;
return ($a < $b) ? -1 : 1;
}
usort($customArr, 'sortByName');
The similar solution as above, but a little different using a temp variable and in a single iteration:
<?php
$str='[{"attribute_code":"budget","value":"141"},{"attribute_code":"restaurants","value":"166"},{"attribute_code":"food_type","value":"172"},{"attribute_code":"budget","value":"142"},{"attribute_code":"restaurants","value":"168"},{"attribute_code":"food_type","value":"173"},{"attribute_code":"budget","value":"143"},{"attribute_code":"restaurants","value":"170"},{"attribute_code":"food_type","value":"173"},{"attribute_code":"budget","value":"162"},{"attribute_code":"restaurants","value":"171"},{"attribute_code":"food_type","value":"172"}]';
$arr = json_decode($str,true);
$temp = $result= [];
foreach($arr as $key=>$customer){
if(in_array($customer['attribute_code'], $temp)){
$index=array_search($customer['attribute_code'],$temp);
if(!in_array($customer['value'],$result[$index]['value'])){
$result[$index]['value'][]=$customer['value'];
}
}else {
$temp[]=$customer['attribute_code'];
$result[]=[
'attribute_code'=>$customer['attribute_code'],
'value'=>[$customer['value']]
];
}
}
unset($temp);
print_r($result);
echo json_encode($result);
?>
Result :
Array
(
[0] => Array
(
[attribute_code] => budget
[value] => Array
(
[0] => 141
[1] => 142
[2] => 143
[3] => 162
)
)
[1] => Array
(
[attribute_code] => restaurants
[value] => Array
(
[0] => 166
[1] => 168
[2] => 170
[3] => 171
)
)
[2] => Array
(
[attribute_code] => food_type
[value] => Array
(
[0] => 172
[1] => 173
)
)
)
JSON ENCODED RESPONSE
[{"attribute_code":"budget","value":["141","142","143","162"]},{"attribute_code":"restaurants","value":["166","168","170","171"]},{"attribute_code":"food_type","value":["172","173"]}]
Hi I have an array of object like this
$json = json_decode($featureJson);
//which returns below
Array
(
[0] => stdClass Object
(
[productID] => 1
[productName] => Toyo
[assessments] => Array
(
[0] => stdClass Object
(
[answer] => Yes
)
[1] => stdClass Object
(
[answer] => Yes
)
...
)
)
[1] => stdClass Object
(
[productID] => 2
[productName] => Maze
[assessments] => Array
(
[0] => stdClass Object
(
[answer] => Yes
)
[1] => stdClass Object
(
[answer] => Yes
)
...
)
)
)
and I have another array that needs to match the ID of $json(Array of Objects) and return its productName.
$string = "1,2|2,1";
$IdArray = explode('|', $string);
$foo = '';
foreach ($IdArray as $item) {
$foo .= '{' . $item . '},';
}
echo $foo;
$foo return {1,2},{2,1} and I match $json so will display - {Toyo,Maze},{Maze,Toyo}, how can I do that? I have some hint using array_map()
but still got no idea to match in objects.
It's easier if you separate an array for the names first.
<?php
$featureJson = '[{"productID":1,"productName":"Toyo","assessments":[{"answer":"Yes"},{"answer":"No"}]},{"productID":2,"productName":"Maze","assessments":[{"answer":"Yes"},{"answer":"Yes"}]}]';
$json = json_decode($featureJson);
// Make an array of names
$names = [];
foreach($json as $products){
$names[$products->productID] = $products->productName;
};
$string = "1,2|2,1";
$IdArray = explode('|', $string);
$foo = [];
foreach ($IdArray as $ids) {
$ids = explode(',',$ids);
$fooItem = [];
foreach($ids as $id){
$fooItem[] = $names[$id];
}
$foo[]= '{' . implode(',',$fooItem) . '}'; }
echo implode(',',$foo);
Result:
{Toyo,Maze},{Maze,Toyo}
Check here
I have an array of php objects that looks something like this:
Array
(
[0] => stdClass Object
(
[order_id] => 1513
[order_total] => 12500.00
[sales_rep] => Doe_John
)
[1] => stdClass Object
(
[order_id] => 1046
[order_total] => 3300.00
[sales_rep] => Doe_John
)
[2] => stdClass Object
(
[order_id] => 337
[order_total] => 4500.00
[sales_rep] => Mosby_Ted
)
)
I am trying to get an array that is set up more like this:
Array
(
[0] => stdClass Object
(
[sales_rep] => Doe_John
[total_sales] => 15800.00
)
[1] => stdClass Object
(
[sales_rep] => Mosby_Ted
[total_sales] => 4500.00
)
)
I want to combine all of the objects with the same "sales_rep" and get the sum of their associated "order_total", which you can see an example of in my desired array above. Any thoughts on how to accomplish this? I've been at it for hours now and have not been able to figure out a solution.
Thanks so much for the help!
try this
$tmp = array();
foreach($objs as $obj){ // where `$objs` is your objects
if(!in_array($obj->sales_rep,array_keys($tmp))){
$tmp[$obj->sales_rep] = (object)array(
'sales_rep' => $obj->sales_rep,
'total_sales' => $obj->order_total
);
}else{
$tmp[$obj->sales_rep]->total_sales += $obj->order_total;
}
}
print_r(array_values($tmp));
$obj0 = new StdClass();
$obj0->order_id = 1513;
$obj0->order_total = 12500.00;
$obj0->sales_rep = 'Doe_John';
$obj1 = new StdClass();
$obj1->order_id = 1046;
$obj1->order_total = 3300.00;
$obj1->sales_rep = 'Doe_John';
$obj2 = new StdClass();
$obj2->order_id = 337;
$obj2->order_total = 4500.00;
$obj2->sales_rep = 'Mosby_Ted';
$array = array(
$obj0,
$obj1,
$obj2,
);
$newArray = array();
foreach ($array as $item) {
if (array_key_exists($item->sales_rep, $newArray)) {
$newObj = $newArray[$item->sales_rep];
$newObj->order_total += $item->order_total;
} else {
$newObj = new StdClass();
$newObj->sales_rep = $item->sales_rep;
$newObj->order_total = $item->order_total;
$newArray[$newObj->sales_rep] = $newObj;
}
}
print_r(array_values($newArray));
I am integrating a payment gateway into a website and their API is returning an xml object where the values I require are nested.
SimpleXMLElement Object
(
[form] => SimpleXMLElement Object
(
[input] => Array
(
[0] => SimpleXMLElement Object
(
[#attributes] => Array
(
[type] => hidden
[name] => SessionStored
[value] => True
)
)
[1] => SimpleXMLElement Object
(
[#attributes] => Array
(
[type] => hidden
[name] => SessionStoredError
[value] =>
)
)
[2] => SimpleXMLElement Object
(
[#attributes] => Array
(
[type] => hidden
[name] => SST
[value] => e19e8abe-a2d6-4ce7
)
)
)
)
)
Using php how can I get the nested attributes into an associative array like the following format?
$array['SessionStored'] = 'True'
$array['SessionStoredError'] = ''
$array['SST'] = 'e19e8abe-a2d6-4ce7'
Its a bit messy but after reading other articles online I have put together the following which throws a 'Fatal error: Call to a member function attributes()'
$xmlData = simplexml_load_string($result);
$aXml = json_decode( json_encode($xmlData) , 1);
$testArray = $aXml['form']['input'];
for($i = 0; $i < count($testArray); $i++)
{
foreach($testArray[$i]->attributes() as $a => $b) {
echo $a,'="',$b,"\"\n";
}
}
Do not try to convert the XML.
Converting XML to JSON means loosing information. Generic conversion does not use the semantic structure. You don't have "nested attributes" just some input element nodes with attribute nodes.
Read it and generate the array from the data.
$result = [];
$element = new SimpleXMLElement($xml);
foreach ($element->form->input as $input) {
$result[(string)$input['name']] = (string)$input['value'];
}
var_dump($result);
Output:
array(3) {
["SessionStored"]=>
string(4) "True"
["SessionStoredError"]=>
string(0) ""
["SST"]=>
string(18) "e19e8abe-a2d6-4ce7"
}
This is easy with DOM, too:
$document = new DOMDocument();
$document->loadXml($xml);
$xpath = new DOMXpath($document);
$result = [];
foreach ($xpath->evaluate('//form/input') as $input) {
$result[$input->getAttribute('name')] = $input->getAttribute('value');
}
var_dump($result);
Basically, I'm receiving an array() from the Yahoo Messenger API in PHP and am in the process of developing an notification system, It returns an array with both the IM received from an chat and my contacts.
Array (
[0] => Array
(
[message] => Array
(
[status] => 1
[sequence] => 0
[sender] => SenderCurtis
[receiver] => receiverCurtis
[msg] => #1
[timeStamp] => 1374187598
[hash] => y2qlDf8uTq8tXzgzrsSMyjQB+W2uDg==
[msgContext] => y2qlDf8uTq8tXzgzrsSMyjQB+W2uDg==
)
)
[1] => Array
(
[buddyInfo] => Array
(
[sequence] => 1
[contact] => Array
(
[0] => Array
(
[sender] => SenderCurtis
[presenceState] => 0
[avatarUser] => 0
[avatarPreference] => 0
[clientCapabilities] => 8915971
[clientUserGUID] => MI7STHUYOAMCGE5TNTY7CJPFWM
)
)
)
)
[2] => Array
(
[message] => Array
(
[status] => 1
[sequence] => 2
[sender] => SenderCurtis
[receiver] => receiverCurtis
[msg] => #2
[timeStamp] => 1374187601
[hash] => 3+2s9sIvjPRdvneQsMgVNCKBTFgKwQ==
[msgContext] => 3+2s9sIvjPRdvneQsMgVNCKBTFgKwQ==
)
)
[3] => Array
(
[buddyInfo] => Array
(
[sequence] => 3
[contact] => Array
(
[0] => Array
(
[sender] => myContactUser1#yahoo.com
[presenceState] => 0
[avatarUser] => 0
[avatarPreference] => 0
[clientCapabilities] => 8915971
[clientUserGUID] => UQU3WV7ZOZ2OTGLJQUE2QJU4ZU
)
)
)
)
)
How can I grab just the message array() and iterate through it? such as "Message 1", "Message2" etc...
If you're trying to filter the array values for the key 'message', you could do something like this in PHP:
$messages = array();
foreach ($response as $key => $data) {
if (array_key_exists('message', $data)) {
$msgArray = $data['message'];
$messages[] = $msgArray;
}
}
In the above sample, I'm storing the messages in their own array. But you could process the data right inside the for-loop too, if you want that.
I think that array_map() is the function you are looking for here. The array_map function allows you to execute a callback on each element of an existing array and assemble a new array consisting only of the values returned by the callback.
What you would want to do is something like this :
$data = // lets assume this is the data you received
$messages_data = array_map( "extract_message", $data );
function extract_message( $data_item ){
if ( array_key_exists( 'message', $data_item ) ){
return $data_item[ 'message' ];
}
}
Now your $message_data array will contain only the message arrays from the original array.
foreach ($var[0] as $key => $value)
{
do things with each message
}
where $var is substituted for your actual variable name
Just filter your array using array_filter.
$messages = array_filter($data, function($a){ return isset($a["message"]); });
Then use array_map to get rid of the unwanted intermediate array.
$messages = array_map(function($a){ return $a["message"]; }, $message);
then you can iterate over it with a foreach or whatever.
Because I like SPL iterators here another solution. Works with PHP >= 5.1.0.
class MessageIterator extends FilterIterator
{
public function accept()
{
return array_key_exists('message', $this->getInnerIterator()->current());
}
public function current()
{
$current = parent::current();
return $current['message'];
}
}
$iterator = new MessageIterator(new ArrayIterator($array));
foreach ($iterator as $message) {
print_r($message);
}