I'm trying to figure out how to get data from the following data structure. I managed to group a flat array into the following array, but am finding it difficult to find the proper resources to explain how to get the data out. I'm looking to get the count of the items in each group. Then i'd like to print the ids from the inner array...
array (
'grinds' =>
array (
0 =>
array (
'id' => 16562,
'slug' => 'grinds',
),
1 =>
array (
'id' => 16561,
'slug' => 'grinds',
),
),
'online-grinds' =>
array (
0 =>
array (
'id' => 16566,
'slug' => 'online-grinds',
),
),
)
$my_array1 = array(
'grinds' =>
array(
0 =>
array(
'id' => 16562,
'slug' => 'grinds',
),
1 =>
array(
'id' => 16561,
'slug' => 'grinds',
),
),
'online-grinds' =>
array(
0 =>
array(
'id' => 16566,
'slug' => 'online-grinds',
),
),
);
get counts:
$counts = array();
foreach ($my_array1 as $key => $val) {
$counts[$key] = count($val);
}
var_dump($counts);
yields:
array(2) {
["grinds"]=>
int(2)
["online-grinds"]=>
int(1)
}
get inner ids:
$innerids = array();
foreach ($my_array1 as $key => $val) {
foreach ($val as $key2 => $val2) {
$innerids[] = $val2['id'];
}
}
var_dump($innerids);
yields:
array(3) {
[0]=>
int(16562)
[1]=>
int(16561)
[2]=>
int(16566)
}
You could use array_map and then for every item use array_column and specifing the field name and then use array_count_values to count the unique values.
Then combine those in an array and use the existing key again as the key for then new array.
$arrays = array_map(function($x) {
return [
array_count_values(array_column($x, 'id')),
array_count_values(array_column($x, 'slug'))
];
}, $arrays);
print_r($arrays);
Result
Array
(
[grinds] => Array
(
[0] => Array
(
[16562] => 1
[16561] => 1
)
[1] => Array
(
[grinds] => 2
)
)
[online-grinds] => Array
(
[0] => Array
(
[16566] => 1
)
[1] => Array
(
[online-grinds] => 1
)
)
)
Demo
Related
I am using php 7.1 and I have the following array:
<?php
$arr = array (
0 =>
array (
'Product' => 'Product1',
'Exact_Match_Keyword' => 'apples freshness',
),
1 =>
array (
'Product' => 'Product1',
'Exact_Match_Keyword' => 'apples',
),
2 =>
array (
'Product' => 'Product1',
'Exact_Match_Keyword' => 'oranges',
),
3 =>
array (
'Product' => 'Product2',
'Exact_Match_Keyword' => 'apples freshness',
),
4 =>
array (
'Product' => 'Product2',
'Exact_Match_Keyword' => 'apples',
),
);
$arr = array_merge_recursive($arr);
var_dump($arr);
/* WANTED DATA STRUCTURE
$arr = array (
0 =>
array (
'Product' => 'Product1',
'Exact_Match_Keyword' => array('apples freshness', 'apples', 'oranges'),
),
1 =>
array (
'Product' => 'Product2',
'Exact_Match_Keyword' => array('apples freshness', 'apples'),
),
);
*/
I tried to use array_merge_recursive however this does not give me my wanted data structure.
Any suggestions what I am doing wrong?
I appreciate your replies!
You can use array_reduce to handle simple logic like this for you. The example below will provide you with the expected format you've posted.
$example = array_values(
array_reduce(
$arr,
static function ($acc, $row) {
if (!isset($acc[$row['Product']])) {
$acc[$row['Product']] = [
'Product' => $row['Product'],
'Exact_Match_Keyword' => [$row['Exact_Match_Keyword']],
];
} else {
$acc[$row['Product']]['Exact_Match_Keyword'] = array_merge(
$acc[$row['Product']]['Exact_Match_Keyword'],
[$row['Exact_Match_Keyword']]
);
}
return $acc;
}
));
print_r($example);
It can be simplified further if the format you expect is flexible:
$example = array_reduce(
$arr,
static function ($acc, $row) {
if (!isset($acc[$row['Product']])) {
$acc[$row['Product']] = [$row['Exact_Match_Keyword']];
} else {
$acc[$row['Product']] = array_merge(
$acc[$row['Product']],
[$row['Exact_Match_Keyword']]
);
}
return $acc;
}
);
print_r($example);
//Output:
//[
// 'Product1'=> ['apples freshness', 'apples', 'oranges'],
// 'Product2'=> ['apples freshness', 'apples']
//]
I think this gets you what you want. Probably not the most graceful thing in the world but it's roughly the logic you'd want to follow.
$temp = [];
foreach ($arr as $v)
{
$pname = $v['Product'];
if (!isset($temp[$pname]))
{
$temp[$pname] = [];
}
$temp[$pname][] = $v['Exact_Match_Keyword'];
}
$out = [];
foreach ($temp as $k => $v)
{
$out[] = [
'Product' => $k,
'Exact_Match_Name' => $v
];
}
php > var_dump($out);
php shell code:1:
array(2) {
[0] =>
array(2) {
'Product' =>
string(8) "Product1"
'Exact_Match_Name' =>
array(3) {
[0] =>
string(16) "apples freshness"
[1] =>
string(6) "apples"
[2] =>
string(7) "oranges"
}
}
[1] =>
array(2) {
'Product' =>
string(8) "Product2"
'Exact_Match_Name' =>
array(2) {
[0] =>
string(16) "apples freshness"
[1] =>
string(6) "apples"
}
}
}
For future reference, if you would like to use the array_merge_recursive() approach on its own, the input data might have to be a little different from what I can tell.
After looking at the example in the documentation page for array_merge_recursive(), I wonder if the original input data needs to be structured a little differently. I think there needs to be matching inner array keys in order for the final array to have something to combine on for the various inner keys. In the example data below, I used the Products key to combine on for the first inner key.
I don't know if it's possible for your starting data to be structured differently for this process, but if the data could look like the following (based on the example on the documentation page for array_merge_recursive()):
<?php
$ar1 = array(
"Products" => array(
"Product1" => array(
"Exact_Match_Keyword" => array('apples freshness')
)
)
);
$ar2 = array(
"Products" => array(
"Product1" => array(
"Exact_Match_Keyword" => array('apples')
)
)
);
$ar3 = array(
"Products" => array(
"Product1" => array(
"Exact_Match_Keyword" => array('oranges')
)
)
);
$ar4 = array(
"Products" => array(
"Product2" => array(
"Exact_Match_Keyword" => array('apples freshness')
)
)
);
$ar5 = array(
"Products" => array(
"Product2" => array(
"Exact_Match_Keyword" => array('apples')
)
)
);
$result = array_merge_recursive($ar1, $ar2, $ar3, $ar4, $ar5);
print_r($result);
The output should then look like this:
Array
(
[Products] => Array
(
[Product1] => Array
(
[Exact_Match_Keyword] => Array
(
[0] => apples freshness
[1] => apples
[2] => oranges
)
)
[Product2] => Array
(
[Exact_Match_Keyword] => Array
(
[0] => apples freshness
[1] => apples
)
)
)
)
I want to remove key 0 from parent array and set child array as parent.
Here I will get single value so one array is ok for me.
My current array looks like this
Array
(
[0] => Array
(
[id] => 3
[api_key] => acount266
[auth_domain] => Tester26
[database_url] => vcc.test.acc+27#gmail.com
[project_id] => 12345
[storage_bucket] =>
[secret_key_path] =>
[fcm_server_key] => 1
[messaging_sender_id] => 0
[key_phrase] =>
[disable] => 0
[created] =>
[updated] =>
)
)
I want it like below. expected result
Array
(
[id] => 3
[api_key] => acount266
[auth_domain] => Tester26
[database_url] => vcc.test.acc+27#gmail.com
[project_id] => 12345
[storage_bucket] =>
[secret_key_path] =>
[fcm_server_key] => 1
[messaging_sender_id] => 0
[key_phrase] =>
[disable] => 0
[created] =>
[updated] =>
)
For this I tried like below but no success.
$new = array();
foreach ($data as $v){
$new = array_merge($new , array_values($v)) ;
}
but in my code it's removed key e.g id,api_key, etc....
I need key name also in my new array. please suggest
Remove the array_values
Solution
<?php
$test = array(
array
(
'id' => 3,
'api_key' => 'acount266'
)
);
$new = array();
foreach($test as $v){
$new = array_merge($new, $v);
}
var_dump($new);
Result
array(2) {
["id"]=>
int(3)
["api_key"]=>
string(9) "acount266"
}
According to documentation of PHP as mentioned
reset() function returns the value of the first array element, or
FALSE if the array is empty.
$array = array(
array(
'id' => 3,
'api_key' => 'acount266',
'auth_domain' => 'Tester26',
'database_url' => 'vcc.test.acc+27#gmail.com',
'project_id' => '12345',
'storage_bucket' => '',
'secret_key_path' => '',
'fcm_server_key' => 1,
'messaging_sender_id' => 0,
'key_phrase' => '',
'disable' => 0,
'created' => '',
'updated' => ''
)
);
print_r(reset($test));
I tried this:
$arr = array();
foreach ($examples as $example) {
foreach ($example as $e) {
array_push($arr, $e);
}
}
Don't overcomplicate this, reassigning the first element to the parent array is quick and easy:
<?php
$array =
array (
0 =>
array (
'first' => 'Michael',
'last' => 'Thompson'
)
);
$array = $array[0];
var_export($array);
Output:
array (
'first' => 'Michael',
'last' => 'Thompson',
)
Or:
$array = array_shift($array);
I do have following associative multidimensional array available after json_decode(string, true).
Array
(
[statusCode] => 200
[data] => Array
(
[objects] => Array
(
[0] => deals
[1] => contacts
[2] => accounts
)
[deals] => Array
(
[0] => dealName
[1] => ApprovedBy
[2] => ApprovedDate
[3] => CloseDate
)
[contacts] => Array
(
[0] => contectName
[1] => email
[2] => firstName
[3] => lastName
)
[accounts] => Array
(
[0] => accountName
[1] => creationDate
[2] => ApprovedDate
[3] => accountNumber
)
)
)
It want to replace numeric keys with their corresponding values in arrays like:
[deals] => deals
[contacts] => contacts
[accounts] => accounts
What I tried so far?
$finalIOArray = array();
$integrationObjectsArray = $response['data']['objects'];
foreach($integrationObjectsArray as $integrationObject){
$finalIOArray[$integrationObject] = $integrationObject;
}
This is for only the objects array in the main data array. But I want to replace keys with values in all the sub-arrays in the main data array.
here's a recursive solution to the problem
function updateArray(array $data)
{
$result = array();
foreach ($data as $key => $value) {
if (is_integer($key) && is_string($value)) { // key is integer and value is string
$result[$value] = $value; // update the key
} elseif (is_array($value)) { // value is array
$result[$key] = updateArray($value); // recurse
} else {
$result[$key] = $value; // leave key/value alone
}
}
return $result;
}
print_r(updateArray($arr));
You can do like this
foreach($arr["data"] as $key=>&$data){
$new = array();
foreach($data as $key2=>$value){
$new[$value] = $value;
}
$data = $new;
}
print_r($arr);
Live demo : https://eval.in/858599
I modify my code to suits your needs, please, try it.
$data = [];
foreach($arr["data"] as $key => $example) {
$new = [];
foreach($example as $value) {
$new[$value] = $value;
}
$data[$key] = $new;
}
$arr["data"] = $data;
print_r($arr);
This is a cleaner and more direct method than the others on offer. Use array_combine to bulk reassign keys using values from the subarray.
In my method using foreach, the & before $data means "passing by reference" . http://php.net/manual/en/language.references.pass.php This effectively allows the modification of the original array data without writing the keys that lead to the specific deep element.
Code:
$arr = Array
(
"statusCode" => 200,
"data" => Array
(
"objects" => Array
(
"0" => deals,
"1" => contacts,
"2" => accounts
),
"deals" => Array
(
"0" => dealName,
"1" => ApprovedBy,
"2" => ApprovedDate,
"3" => CloseDate
),
"contacts" => Array
(
"0" => contectName,
"1" => email,
"2" => firstName,
"3" => lastName
),
"accounts" => Array
(
"0" => accountName,
"1" => creationDate,
"2" => ApprovedDate,
"3" => accountNumber
)
)
);
foreach($arr["data"] as &$data){
$data=array_combine($data,$data);
}
var_export($arr);
Output:
array (
'statusCode' => 200,
'data' =>
array (
'objects' =>
array (
'deals' => 'deals',
'contacts' => 'contacts',
'accounts' => 'accounts',
),
'deals' =>
array (
'dealName' => 'dealName',
'ApprovedBy' => 'ApprovedBy',
'ApprovedDate' => 'ApprovedDate',
'CloseDate' => 'CloseDate',
),
'contacts' =>
array (
'contectName' => 'contectName',
'email' => 'email',
'firstName' => 'firstName',
'lastName' => 'lastName',
),
'accounts' =>
array (
'accountName' => 'accountName',
'creationDate' => 'creationDate',
'ApprovedDate' => 'ApprovedDate',
'accountNumber' => 'accountNumber',
),
),
)
Or if you prefer functional iteration, this provides the same output.
$arr["data"]=array_map(function ($a){return array_combine($a,$a);},$arr["data"]);
var_export($arr);
Array (
[0] => Array (
[OrderProduct] => Array (
[pro_code] => B1
[totalQTY] => 4
)
)
[1] => Array (
[OrderProduct] => Array (
[pro_code] => B2
[totalQTY] => 4
)
)
[2] => Array (
[OrderProduct] => Array (
[pro_code] => B4
[totalQTY] => 4
)
)
)
Array (
[0] => Array (
[OrderProduct] => Array (
[pro_code] => B1
[totalDistSalesQTY] => 360
)
)
[1] => Array (
[OrderProduct] => Array (
[pro_code] => B2
[totalDistSalesQTY] => 600
)
)
[2] => Array (
[OrderProduct] => Array (
[pro_code] => B3
[totalDistSalesQTY] => 600
)
)
)
I would like to merge the two arrays above on the pro_code value. This is the expected result:
Array (
[0] => Array (
[OrderProduct] => Array (
[pro_code] => B1
[totalDistSalesQTY] => 360
[totalQTY] => 4
)
)
[1] => Array (
[OrderProduct] => Array (
[pro_code] => B2
[totalDistSalesQTY] => 600
[totalQTY] => 4
)
)
[2] => Array (
[OrderProduct] => Array (
[pro_code] => B3
[totalDistSalesQTY] => 600
)
)
[3] => Array (
[OrderProduct] => Array (
[pro_code] => B4
[totalQTY] => 4
)
)
)
I want to merge multiple array. Please help me to merge it properly. I applied many techniques to merge it. Still I could not find my way. Please help me with this issue.
So basically, what you have to do, is implement a merge algorithm on a sequence. It is one of the basic programming theses, so it shouldn't be too hard.
First, you have to sort the sequences in ascending order (the arrays in the example) by a unique, strictly sortable value (this is the pro_code in here).
Second, you need to iterate through both sequences at the same time.
If the current items unique key (pro_code) match, merge them and push to the result array, if not push the one with the lesser key to the result array. After pushing, increase the index of the pushed sequence by one.
After reaching the end of one of the sequences, push the rest to the result array.
And this is how it looks implemented in php:
<?php
// Compare func for usort
function compare($a, $b) {
return strcmp($a['OrderProduct']['pro_code'], $b['OrderProduct']['pro_code']);
}
// Sort array with usort
function sort_array(&$a) {
usort($a, 'compare');
}
// Print array
function print_a(&$a) {
print '<pre>';
print_r($a);
print '</pre>';
}
function list_merge(&$a, &$b) {
$resp = array();
$ia = 0;
$ib = 0;
while($ia < count($a) || $ib < count($b)) {
// Check if any of the arrays reached its end
// If not, check for merge
if(isset($a[$ia]) && isset($b[$ib])) {
// Product codes are matching,
// Push merged to $resp
if(strcmp($a[$ia]['OrderProduct']['pro_code'], $b[$ib]['OrderProduct']['pro_code']) == 0) {
$resp[] = array(
'OrderProduct' => array(
'pro_code' => $a[$ia]['OrderProduct']['pro_code'],
'totalQTY' => $a[$ia]['OrderProduct']['totalQTY'] + $b[$ib]['OrderProduct']['totalQTY'],
),
);
// If merge increment both
$ia++;
$ib++;
}
// Product code of element of $a is lesser,
// Push $a to $resp
elseif(strcmp($a[$ia]['OrderProduct']['pro_code'], $b[$ib]['OrderProduct']['pro_code']) < 0) {
$resp[] = array(
'OrderProduct' => array(
'pro_code' => $a[$ia]['OrderProduct']['pro_code'],
'totalQTY' => $a[$ia]['OrderProduct']['totalQTY'],
),
);
// Increment only pushed
$ia++;
}
// Product code of element of $b is lesser,
// Push $b to $resp
else {
$resp[] = array(
'OrderProduct' => array(
'pro_code' => $b[$ib]['OrderProduct']['pro_code'],
'totalQTY' => $b[$ib]['OrderProduct']['totalQTY'],
),
);
// Increment only pushed
$ib++;
}
}
// Else automatically push the existing array
// If $a exists
elseif(isset($a[$ia])) {
$resp[] = array(
'OrderProduct' => array(
'pro_code' => $a[$ia]['OrderProduct']['pro_code'],
'totalQTY' => $a[$ia]['OrderProduct']['totalQTY'],
),
);
// Increment only pushed
$ia++;
}
// Else automatically push the existing array
// If $b exists
else {
$resp[] = array(
'OrderProduct' => array(
'pro_code' => $b[$ib]['OrderProduct']['pro_code'],
'totalQTY' => $b[$ib]['OrderProduct']['totalQTY'],
),
);
// Increment only pushed
$ib++;
}
}
return $resp;
}
// Data structures
$array1 = array(
array(
'OrderProduct' => array(
'pro_code' => 'B1',
'totalQTY' => 4,
),
),
array(
'OrderProduct' => array(
'pro_code' => 'B2',
'totalQTY' => 4,
),
),
array(
'OrderProduct' => array(
'pro_code' => 'B4',
'totalQTY' => 4,
),
),
);
$array2 = array(
array(
'OrderProduct' => array(
'pro_code' => 'B1',
'totalQTY' => 360,
),
),
array(
'OrderProduct' => array(
'pro_code' => 'B2',
'totalQTY' => 600,
),
),
array(
'OrderProduct' => array(
'pro_code' => 'B3',
'totalQTY' => 600,
),
),
);
// Sort arrays by product code
sort_array($array1);
sort_array($array2);
// Merge arrays with list merge
$array3 = list_merge($array1, $array2);
// Print arrays for check
print_a($array1);
print_a($array2);
print_a($array3);
I hope, I could be of any help.
This is as condensed as I can make my method. It is effectively 3 simple steps with a custom function.
Code:
$QTY=[
["OrderProduct"=>
["pro_code"=>"B1","totalQTY"=>"4"]],
["OrderProduct"=>
["pro_code"=>"B2","totalQTY"=>"4"]],
["OrderProduct"=>
["pro_code"=>"B4","totalQTY"=>"4"]]
];
$DSQTY=[
["OrderProduct" =>
["pro_code"=>"B1","totalDistSalesQTY"=>"360"]],
["OrderProduct"=>
["pro_code"=>"B2","totalDistSalesQTY"=>"600"]],
["OrderProduct"=>
["pro_code"=>"B3","totalDistSalesQTY"=>"600"]]
];
function getDeepColumn($a,$c,$result=[]){
foreach(array_column(array_column($a,"OrderProduct"),$c,'pro_code') as $k=>$v){
$result[$k][$c]=$v;
}
return $result;
}
$merged=array_merge_recursive(getDeepColumn($QTY,'totalQTY'),getDeepColumn($DSQTY,'totalDistSalesQTY'));
ksort($merged); // make sure B4 is not before B3
foreach($merged as $k=>$a){
$result[]=["OrderProduct"=>array_merge(["pro_code"=>$k],$a)];
}
var_export($result);
Custom function explanation: getDeepColumn() uses array_column() with a nominated array and a nominated column name to extract the desired values from all OrderProduct subarrays. The column values are temporarily stored in an array of arrays called $result. $result's first level keys are pro_code values for future merging purposes. $result's subarrays consist of the nominated column's name (as key) and the nominated column's value (as values).
First, use array_merge_recursive() to blend together the desired deep column values.
Next, $merge is ksort()'ed (using the unique pro_code keys).
Finally, using foreach(), re-index all OrderProduct subarrays, and return the pro_code value to its rightful place inside the OrderProduct subarray.
Output:
array (
0 =>
array (
'OrderProduct' =>
array (
'pro_code' => 'B1',
'totalQTY' => '4',
'totalDistSalesQTY' => '360',
),
),
1 =>
array (
'OrderProduct' =>
array (
'pro_code' => 'B2',
'totalQTY' => '4',
'totalDistSalesQTY' => '600',
),
),
2 =>
array (
'OrderProduct' =>
array (
'pro_code' => 'B3',
'totalDistSalesQTY' => '600',
),
),
3 =>
array (
'OrderProduct' =>
array (
'pro_code' => 'B4',
'totalQTY' => '4',
),
),
)
This is pretty simple if you use the product code as a key in the result array.
// combine the two arrays together and iterate all their rows
foreach (array_merge($array1, $array2) as $row) {
// get the code
$code = $row['OrderProduct']['pro_code'];
// get the previous value for that code, or an empty array if there isnt' one
$prev = $result[$code]['OrderProduct'] ?? [];
// merge the previous value with the new value
$result[$code]['OrderProduct'] = array_merge($prev, $row['OrderProduct']);
}
You'll end up with product code keys in your result array, which is probably fine. If it's not fine, you can remove them with $result = array_values($result).
I have two arrays:
Array
(
[0] => Array
(
[id] => 1
[type] => field
[remote_name] => Title
[my_name] => title
[default_value] => http%3A%2F%2Ftest.com
)
[1] => Array
(
[id] => 2
[type] => field
[remote_name] => BookType
[my_name] => book-type
[default_value] =>
)
[2] => Array
(
[id] => 3
[type] => value
[remote_name] => dvd-disc
[my_name] => dvd
[default_value] =>
)
)
Array
(
[title] => Test
[book-type] => dvd
)
I need to take each key in the second array, match it with the my_name value in the first array and replace it with the corresponding remote_name value of the first array while preserving the value of the second array.
There's got to be some carrayzy function to help!
EDIT: There will also be a few cases that the value of the second array will need to be replaced by the value of the first array's remote_name where the value of the second array matches the value of the first array's my_name. How can I achieve this?
EG: book-type => dvd should turn into BookType => dvd-disc
Like so?:
$first = array(
array(
'id' => 1,
'type' => 'field',
'remote_name' => 'Title',
'my_name' => 'title',
'default_value' => 'http%3A%2F%2Ftest.com',
),
array(
'id' => 2,
'type' => 'field',
'remote_name' => 'BookType',
'my_name' => 'book-type',
'default_value' => '',
),
array(
'id' => 3,
'type' => 'value',
'remote_name' => 'dvd-disc',
'my_name' => 'dvd',
'default_value' => '',
),
);
$second = array(
'title' => 'Test',
'book-type' => 'dvd',
);
$map = array('fields' => array(), 'values' => array());
foreach ($first as $entry) {
switch ($entry['type']) {
case 'field':
$map['fields'][$entry['my_name']] = $entry['remote_name'];
break;
case 'value':
$map['values'][$entry['my_name']] = $entry['remote_name'];
break;
}
}
$new = array();
foreach ($second as $key => $val) {
$new[isset($map['fields'][$key]) ? $map['fields'][$key] : $key] = isset($map['values'][$val]) ? $map['values'][$val] : $val;
}
print_r($new);
Output:
Array
(
[Title] => Test
[BookType] => dvd-disc
)
Explanation:
The first loop collects the my_name/remote_name pairs for fields and values and makes them more accessible.
Like so:
Array
(
[fields] => Array
(
[title] => Title
[book-type] => BookType
)
[values] => Array
(
[dvd] => dvd-disc
)
)
The second loop will traverse $second and use the key/value pairs therein to populate $new. But while doing so will check for key/value duplicates in $map.
Keys or values not found in the map will be used as is.
foreach($arr1 as &$el) {
$el['remote_name'] = $arr2[$el['my_name']];
}
unset($el);
I am not aware of such a carrayzy function, but I know how you could do it:
//$array1 is first array, $array2 is second array
foreach($array1 as $key => $value){
if (isset($value['remote_name'], $value['my_name']) && $value['remote_name'] && $value['my_name']){
$my_name = $value['my_name'];
if (isset($array2[$my_name])) {
$remote_name = $value['remote_name'];
$array2[$remote_name] = $array2[$my_name];
//cleanup
unset($array2[$my_name]);
}
}
}