This array_merge doesn't seem to work for me. I am trying merge all the arrays in one array like this:
foreach ($collection as $result) {
$i++;
if(empty($json)){
$json = $result->getData();
}else{
$json = array_merge($json, $result->getData());
}
}
print_r($json);
I have 3 arrays in the collection. But when I do print_r($json); it only shows me the last array like this.
Array (
[po_id] => 3
[title] => Test3
[geo_address] => M1 2FF
[latitude] => 53.449137
[longitude] => -2.364551
[display_address] => testing
[url] => http://testing.com
[phone] => 0321654987
[status] => 1
[type] => 1
[created_time] => 2012-01-26 11:07:05
[update_time] => 2012-01-26 11:10:13
[distance] => 3708.40724665926
)
I am expecting this to merge all three arrays and print that out.
I'm kinda expecting it like this:
Array (
[po_id] => 1
[title] => Test1
[geo_address] => M1 2FF
[po_id] => 2
[title] => Test2
[geo_address] => M2 2FF
[po_id] => 3
[title] => Test3
[geo_address] => M3 2FF
)
Means all the arrays should be merged in on array.
EDITTED
I have it working. In fact this what I was looking for:
$json = array();
foreach ($collection as $key=>$result) {
$data = $result->getData();
$json[$key]['postorefinder_id'] = $data['postorefinder_id'];
$json[$key]['title'] = $data['title'];
$json[$key]['geo_address'] = $data['geo_address'];
$json[$key]['latitude'] = $data['latitude'];
$json[$key]['latitude'] = $data['latitude'];
$json[$key]['longitude'] = $data['longitude'];
$json[$key]['display_address'] = $data['display_address'];
$json[$key]['url'] = $data['url'];
$json[$key]['phone'] = $data['phone'];
$json[$key]['status'] = $data['status'];
$json[$key]['type'] = $data['type'];
$json[$key]['created_time'] = $data['created_time'];
$json[$key]['update_time'] = $data['update_time'];
$json[$key]['distance'] = $data['distance'];
}
return json_encode($json);
Thanks #cillosis, your example really helped.
According to the array_merge() function on php.net:
If the input arrays have the same string keys, then the later value for that key will overwrite the previous one. If, however, the arrays contain numeric keys, the later value will not overwrite the original value, but will be appended.
This means, every time you try to merge them, because they are using the same key, it just gets overwritten. That's why you only see the last array.
[EDIT]
So how would I concatenate multiple arrays with the same keys in one array?
I don't see how two elements can share the same key unless that key contained another array like this:
foreach ($collection as $result) {
// Get collection of data
$data = $result->getData();
// Assign each result to multi-dimensional array
$json['po_id'][] = $data['po_id'];
$json['title'][] = $data['title'];
$json['geo_address'][] = $data['geo_address'];
$json['latitude'][] = $data['latitude'];
// ... the rest of them go here ...
}
That is untested, just threw it together real quick. It should output something like:
Array(
"po_id": Array(
"first_po_id",
"second_po_id",
"third_po_id"
),
"title": Array(
"first_title",
"second_title",
"third_title"
)
)
With more data than that of course.
Unfortunately the structure you're hoping for is not possible in PHP. Have a read about the array type; if you try to assign a value to a pre-existing key, it overwrites any existing value:
$array = array('foo' => 'bar');
$array = array_merge($array, array('foo' => 'new'));
var_dump($array['foo']); // new
Depending on how you want to manipulate the resulting data, you can use array_merge_recursive:
$json = array();
foreach ($collection as $result) {
$json = array_merge_recursive($json, $result->getData());
}
or alternatively you might want the collections to group by result:
// make $json a copy of $collection
$json = $collection;
// overwrite $result within $json
foreach ($json as &$result) {
$result = $result->getData();
}
EDIT: See example output for each of these approaches.
Related
I have a PHP array which contains objects like this
Array
(
[0] => stdClass Object
(
[label] => Test 1
[session] => 2
)
[1] => stdClass Object
(
[label] => Test 2
[session] => 2
)
[2] => stdClass Object
(
[label] => Test 3
[session] => 42
)
[3] => stdClass Object
(
[label] => Test 4
[session] => 9
)
)
I am trying to count the number of unique sessions within this array. I can do it when the whole thing is an array, but I am struggling to work it out when the array contains objects.
Do I need to convert the objects into arrays or is there a way of doing it with the data in its current format?
https://www.php.net/manual/en/function.array-column.php :
Version Description
7.0.0 Added the ability for the input parameter to be an array of objects.
Use array_column to generate new keys using the session column values. This effectively removes duplicate keys.
Code: (Demo)
$array = [
(object)['label' => 'Test 1', 'session' => 2],
(object)['label' => 'Test 2', 'session' => 2],
(object)['label' => 'Test 3', 'session' => 42],
(object)['label' => 'Test 4', 'session' => 9],
];
echo sizeof(array_column($array, null, 'session'));
Output:
3
Or in a loop:
foreach ($array as $obj) {
$result[$obj->session] = null;
}
echo sizeof($result);
Both techniques avoid the extra function call of array_unique and leverage the fact that arrays cannot store duplicate keys.
I have tried your code and here created sample data
$comments= array();
$comment = new stdClass;
$comment->label = 'Test 1';
$comment->session = '2';
array_push($comments, $comment);
$comment = new stdClass;
$comment->label = 'Test 2';
$comment->session = '2';
array_push($comments, $comment);
$comment = new stdClass;
$comment->label = 'Test 3';
$comment->session = '42';
array_push($comments, $comment);
$comment = new stdClass;
$comment->label = 'Test 4';
$comment->session = '9';
array_push($comments, $comment);
Here is code I tried to get the unique value. this way you can get any field unique value
$uniques = array();
foreach ($comments as $obj) {
$uniques[$obj->session] = $obj;
}
echo "<pre>";
print_r($uniques);
echo "</pre>";
You could also use array_map to only keep the value of session in the array, then use array_unique to remove the duplicate entries and finally count the unique items.
If for example your array variable is called $array:
$result = array_map(function($x){
return $x->session;
}, $array);
echo count(array_unique($result));
That will result in:
3
Demo
The object within an array can be accessed with $array[0] where the 0 stands for the object. To access the objects property you can do $object->session.
To go throught every objects session property you can do:
foreach ($array as $object) {
echo $object->session . "<br/>";
}
I want to combine several arrays into one, they are the result of a form post with an unknown number of elements, eg:
$ids = [53,54,55];
$names = ['fire','water','earth'];
$temps = [500,10,5];
What i want is to make a function that takes these arrays as an input and produces a single output, like
$elements = [['id'=>53,'name'=>'fire','temp'=>500] , ['id'=>54,'name'=>'water','temp'=>500] , ['id'=>55,'name'=>'earth','temp'=>500]]
I came up with the following solution:
function atg($array) {
$result = array();
for ($i=0;$i<count(reset($array));$i++) {
$newAr = array();
foreach($array as $index => $val) {
$newAr[$index] = $array[$index][$i];
}
$result[]=$newAr;
}
return $result;
}
It can be called like
$elements = atg(['id' => $ids, 'name' => $names, 'temp' => $temps]);
And it produces the right output. To me it seems a bit overly complicated though, and I'm sure this is a common problem in PHP for form posts, combining seperate fields into a single array per item. What would be a better solution?
You can loop through all of your 3 arrays at once with array_map(). There you can just return the new array with a value of each of the 3 arrays, e.g.
$result = array_map(function($id, $name, $temp){
return ["id" => $id, "name" => $name, "temp" => $temp];
}, $ids, $names, $temps);
Use below code:-
$ids = [53,54,55];
$names = ['fire','water','earth'];
$temps = [500,10,5];
$result = [];
foreach($ids as $k=>$id){
$result[$k]['id'] = $id;
$result[$k]['name'] =$names[$k];
$result[$k]['temp'] = $temps[0];
}
echo '<pre>'; print_r($result);
output:-
Array
(
[0] => Array
(
[id] => 53
[name] => fire
[temp] => 500
)
[1] => Array
(
[id] => 54
[name] => water
[temp] => 500
)
[2] => Array
(
[id] => 55
[name] => earth
[temp] => 500
)
)
If you are ok with a destructive solution, array_shift could do the trick :
$elements = array();
while (!empty($ids)) {
$elements[] = array(
'id' => array_shift($ids),
'name' => array_shift($names),
'temp' => array_shift($temps),
);
}
If you want to make a function, using the same arguments than your example, a solution could be
function atg($array) {
$elements = array();
while (!empty($array[0])) {
$new_element = array();
foreach ($array as $key_name => $array_to_shift) {
$new_element[$key_name] = array_shit($array_to_shift);
}
$elements[] = $new_element;
}
return $elements;
}
$result[$ids]['name'] = $names[0];
$result[$ids]['temp'] = $temps[0]
I have an array ($datesandadults) with pairs of values which are the date and the number of people:
Array (
[0] => stdClass Object (
[thedate] => April 9, 2016
[theadults] => 6
)
[1] => stdClass Object (
[thedate] => April 10, 2016
[theadults] => 9
)
...
I need to modify thedate value then put everything back into a new similar structured array. my code doesn't work, all it gives is:
Array (
[0] => date
[1] => adults
[thedate] => 2016-04-09
[adults] => )
The code I am using is:
$final_results = array('thedate','adults');
foreach ($datesandadults as $res2) {
foreach( $res2 as $key => $value) {
if ($key=='thedate') {
$actualtime=strtotime($value);
$value = date('Y-m-d', $actualtime);
}
$final_results[thedate] = $res2->thedate;
$final_results[adults] = $res2->adults;
}
}
I know my current code is nonsense but maybe will give an idea what I need..
You have an array of objects, not arrays. You need to loop through the objects, creating a new array. You can access the object properties directly, so you do not need the interior foreach loop.
// initialize empty result array
$final_results = []; // use array() for PHP < 5.4
foreach ($datesandadults as $res2) {
// convert original date value
$actualtime = strtotime($res2->thedate);
$date_value = date('Y-m-d', $actualtime);
// create new object with updated values
$new_object = (object) array(
'thedate' => $date_value,
'theadults' => $res2->theadults
);
// add new object to result array
$final_results[] = $new_object;
}
First, you may want $final_results to be an empty array, so:
$final_results = array();
Then, you may want to restructure your second loop, so it gets every object from the first one, takes the needed information, and then put it back in the new one. Like this:
foreach ($datesandadults as $res2) {
$thedate = '';
$theadults = '';
foreach( $res2 as $key => $value) {
if ($key=='thedate') {
$actualtime=strtotime($value);
$thedate = date('Y-m-d', $actualtime);
}else if($key=='theadults'){
$theadults = $value;
}
}
$final_results[] = array(
'thedate'=>$thedate,
'theadults'=>$theadults
);
}
Or just skip the second loop and access the values directly
Assuming that I have an array of objects like this:
Array
(
[0] => stdClass Object
(
[id] => 10-423-1176
[qty] => 2
[price] => 12.6
)
[1] => stdClass Object
(
[id] => 26-295-1006
[qty] => 24
[price] => 230.35
)
[2] => stdClass Object
(
[id] => 12-330-1000
[qty] => 2
[price] => 230.35
)
And I have another array of object hat looks like this:
Array
(
[0] => Item Object
(
[internalId] => 14062
[itemVendorCode] => 89-605-1250
)
[1] => Item Object
(
[internalId] => 33806
[itemVendorCode] => 89-575-2354
)
[2] => Item Object
(
[internalId] => 64126
[itemVendorCode] => 26-295-1006
)
)
I want to loop through the 2nd array of objects and get the 'itemVendorCode' and then use it as the 'id' to get the object from the first array of objects. Is there a way to obtain what I want without looping the first array? Looping is very costly in my use-case.
You will have to use loops in any case, even if those loops are hidden within PHP built-in functions.
For instance:
$codes = array_map(function ($item) { return $item->itemVendorCode; }, $array2);
$items = array_filter($array1, function ($item) use ($codes) { return in_array($item->id, $codes); });
// $items contains only elements from $array1 that match on $array2
If this will be more efficient than using regular loops is hard to tell.
Since you are aparently trying to code what is supposed to be a DBMS's job, I recommend you export those tables to a database server such as MySQL instead and let it work its magic on those "JOINs".
Answering your comment, you could merge with something like this:
$result = array();
foreach ($array1 as $item1)
foreach ($array2 as $item2)
if ($item1->id == $item2->itemVendorCode)
$result[] = (object)array_merge((array)$item1, (array)$item2));
$result will contain a new set of objects that merge properties from both $array1 and $array2 where they intersect in id == itemVendorCode.
Do you need first arrays index keys? if not you could iterate throuh first array once and set key to id. Something like:
foreach ($items as $key => $item) {
$items[$item->id] = $item;
unset($items[$key]);
}
Here is another direct approach to solve this problem, even better than the one I proposed earlier:
// you got the $itemVendorCode from looping through the second array, let say :
$itemVendorCode = "89-605-1250";
// I'm assuming that you converted the array of objects in into accessible multidimensional array
// so the $first_array would look like :
$first_array= array (
array (
"id" => "10-423-1176",
"qty" => 2,
"price" => 12.6
),
array (
"id" => "10-423-1176",
"qty" => 5,
"price" => 25
),
array (
"id" => "89-605-1250",
"qty" => 12,
"price" => 30
)
);
// Now you can filter the first array using
$filter = function ($player) use($itemVendorCode) {
return $player ['id'] == $itemVendorCode;
};
$filtered = array_filter ( $first_array, $filter );
// print the price of the matching filtered item
print $filtered[key($filtered)]['price'] ;
You can use the array_map and array_filter() function to achieve that.
Try with this code:
<?php
$first = array();
$first[0] = new stdClass;
$first[0]->id = '89-605-1250';
$first[0]->qty = 2;
$first[0]->price = 12.6;
$first[1] = new stdClass;
$first[1]->id = '89-575-2354';
$first[1]->qty = 24;
$first[1]->price = 230.35;
$last = array();
$last[0] = new stdClass;
$last[0]->internalId = 14062;
$last[0]->itemVendorCode = '89-605-1250';
$last[1] = new stdClass;
$last[1]->internalId = 33806;
$last[1]->itemVendorCode = '89-575-2354';
$ids = array_map(function($element){return $element->itemVendorCode;}, $last);
$to_find = $ids[0];
$object = array_filter($first, function($element){global $to_find; return $element->id == $to_find ? true: false;})[0];
print_r($object);
?>
Output:
stdClass Object
(
[id] => 89-605-1250
[qty] => 2
[price] => 12.6
)
try using array_search:
http://php.net/manual/en/function.array-search.php
foreach($array2 as $key=>$item) {
$firstArrayObjectKey = array_search($item['itemVendorCode'], $array1);
//... do something with the key $firstArrayObjectKey
}
In this case you'll need to loop through the first array to get the itemVendorCode.
Right after that you can use the itemValue you got from the previous process to search in a reduced array of the first object using array_reduce function:
http://php.net/manual/en/function.array-reduce.php
The multiple array looks like
Array
(
[id] => description
[header] =>
[width] => 20
[dbfield] => description
[type] => text
)
Array
(
[id] => quantity
[header] => Menge
[dbfield] => QUANTITY_NEW
[width] => 60
[type] => decimal
)
How can I get the value from dbfield where id is 'quantity' without knowing the numeric value of the id?
The actual code looks like
foreach($array as $id => $fieldData) {
if($fieldData['type'] == 'decimal')
{
doSomething...();
}
}
In the part with doSomething I need access to other fields from the array, but I only know the id. I already tried it with dbfield['quantity']['dbfield'] etc. which obviously fails.
A simple alternative using array_keys:
function getValues($data, $lookForValue, $column)
{
$res = array();
foreach ($data as $key => $data)
{
if($idx = array_keys($data, $lookForValue))
{
$res[$idx[0]] = $data[$column];
}
}
return $res;
}
$values = getValues($myData, "quantity", "dbfield");
var_dump($values);
echo out the array as such..
$array = array();
$array['qty'] = 'qtty';
$array['dbfield'] = 'QUANTITY_NEW';
if($array['qty'] = 'qtty'){
echo $array['dbfield'];
}
returns - QUANTITY_NEW
You can do this with several methods, one of them is using array_map to get those values:
$dbfield = array_filter(array_map(function($a){
if($a["id"] === "quantity"){
return $a["dbfield"];
}
}, $array));
print_r($dbfield);
You iterate over the array, and return the key dbfield where id is 'quantity'. Array filter is just to not return null values where it doesn't have 'quantity' id.
Online attempt to reproduce your code can be found here