I am trying to uniformly rename all of my array keys using a foreach loop and unset.
Array before:
Array
( [0] => Array (
[store_nl] => Store One
[id_nl] => 123456
[title_nl] => Product One
[price_nl] => $9.00 )
[1] => Array (
[store_ds] => Store Two
[id_ds] => 789012
[title_ds] => Product Two
[price_ds] => $8.00 )
)
foreach using unset:
if(isset($data)){
foreach ( $data as $k=>$v )
{
//Store One (ds)
$data[$k]['Store'] = $data[$k]['store_ds'];
$data[$k]['ItemID'] = $data[$k]['id_ds'];
$data[$k]['Description'] = $data[$k]['title_ds'];
$data[$k]['Price'] = $data[$k]['price_ds'];
unset($data[$k]['store_ds']);
unset($data[$k]['id_ds']);
unset($data[$k]['title_ds']);
unset($data[$k]['price_ds']);
//Store Two (nl)
$data[$k]['Store'] = $data[$k]['store_nl'];
$data[$k]['ItemID'] = $data[$k]['id_nl'];
$data[$k]['Description'] = $data[$k]['title_nl'];
$data[$k]['Price'] = $data[$k]['price_nl'];
unset($data[$k]['store_nl']);
unset($data[$k]['id_nl']);
unset($data[$k]['title_nl']);
unset($data[$k]['price_nl']);
}
}
Array after:
Array
( [0] => Array (
[Store] => Store One
[ItemID] => 123456
[Description] => Product One
[Price] => $9.00 )
[1] => Array (
[Store] =>
[ItemID] =>
[Description] =>
[Price] => )
)
All of the array keys have been changed, but some of the data is now gone? Can someone please tell me a better way to do this without data loss?
The following will do what you deed:
$myArray = array(
array(
'store_ni' => 'Store One',
'id_ni' => 123456,
'title_ni' => 'Product One',
'price_ni' => '$9.00'
),
array(
'store_ds' => 'Store Two',
'id_ds' => 789012,
'title_ds' => 'Product Two',
'price_ds' => '$8.00'
)
);
$newKeys = array('Store', 'ItemID', 'Description', 'Price');
$result = array();
foreach($myArray as $innerArray)
{
$result[] = array_combine(
$newKeys,
array_values($innerArray)
);
}
array_combine() combines the first array you pass to it and assign it as the keys of the returned array and the second array you pass it as the values of that array.
Use array_flip() to flip between the keys and values, then it'll be easy to run over the values and "flip" the array again (back to its original state). It should be something like:
$tmp_arr = array_flip($arr);
$fixed_arr = array();
foreach($tmp_arr as $k => $v){
if($val == "store_nl"){
$fixed_arr[$k] = "Store";
}
// etc...
}
// and now flip back:
$arr = array_flip($fixed_arr);
The arrays should have the same number of elements, but I think that's the case here.
$data = [[
'store_nl' => 'Store One',
'id_nl' => 123456,
'title_nl' => 'Product One',
'price_nl' => '$9.00'
], [
'store_ds' => 'Store Two',
'id_ds' => 789012,
'title_ds' => 'Product Two',
'price_ds' => '$8.00'
]];
$keys = ['Store', 'ItemID', 'Description', 'Price'];
$data = [
'nl' => array_combine($keys, $data[0]),
'ds' => array_combine($keys, $data[1])
];
Recursive php rename keys function:
function replaceKeys($oldKey, $newKey, array $input){
$return = array();
foreach ($input as $key => $value) {
if ($key===$oldKey)
$key = $newKey;
if (is_array($value))
$value = replaceKeys( $oldKey, $newKey, $value);
$return[$key] = $value;
}
return $return;
}
Related
I have a multidimensional array and am trying to group them according to the value in a specific column.
I'm trying to group them by level, but I won't actually know the level beforehand. So, it's not like I can put it in a for loop and say while $i < 7, because I won't know that 7 is the maximum value for the level key, and frankly, I'm not sure that's how I would need to do it even if I did.
[
['cust' => 'XT8900', 'type' => 'standard', 'level' => 1],
['cust' => 'XT8944', 'type' => 'standard', 'level' => 1],
['cust' => 'XT8922', 'type' => 'premier', 'level' => 3],
['cust' => 'XT8816', 'type' => 'permier', 'level' => 3],
['cust' => 'XT7434', 'type' => 'standard', 'level' => 7],
]
Desired result:
Array (
[1] => Array (
[0] => Array (
[cust] => XT8900
[type] => standard
)
[1] => Array (
[cust] => XT8944
[type] => standard
)
)
[3] => Array (
[2] => Array (
[cust] => XT8922
[type] => premier
)
[3] => Array (
[cust] => XT8816
[type] => permier
)
)
[7] => Array (
[4] => Array (
[cust] => XT7434
[type] => standard
)
)
)
Best way, if you have control over building the initial array, is just set things up like that at the start as you add entries.
If not then build a temporary array to sort:
foreach ($input_arr as $key => &$entry) {
$level_arr[$entry['level']][$key] = $entry;
}
Leaves you with the form you wanted and everything referenced together.
Build the array like that in the first place though if at all possible.
You need to group them by level first
Use foreach to loop into array check if the level is the same with the previous item then group it with that array
$templevel=0;
$newkey=0;
$grouparr[$templevel]="";
foreach ($items as $key => $val) {
if ($templevel==$val['level']){
$grouparr[$templevel][$newkey]=$val;
} else {
$grouparr[$val['level']][$newkey]=$val;
}
$newkey++;
}
print($grouparr);
The output of print($grouparr); will display like the format you hoped for
You can also try to
print($grouparr[7]);
Will display
[7] => Array (
[4] => Array (
[cust] => XT7434
[type] => standard
)
)
Or
print($grouparr[3]);
Will display
[3] => Array (
[2] => Array (
[cust] => XT8922
[type] => premier
)
[3] => Array (
[cust] => XT8816
[type] => permier
)
)
Here is the solution I landed on for an identical problem, wrapped as a function:
function arraySort($input,$sortkey){
foreach ($input as $key=>$val) $output[$val[$sortkey]][]=$val;
return $output;
}
To sort $myarray by the key named "level" just do this:
$myArray = arraySort($myArray,'level');
Or if you didn't want it as a function, just for a one time use, this would create $myNewArray from $myArray grouped by the key 'level'
foreach ($myArray as $key=>$val) $myNewArray[$val['level']][]=$val;
function group_assoc($array, $key) {
$return = array();
foreach($array as $v) {
$return[$v[$key]][] = $v;
}
return $return;
}
//Group the requests by their account_id
$account_requests = group_assoc($requests, 'account_id');
$result = array();
foreach ($yourArrayList as $data) {
$id = $data['level'];
if (isset($result[$id])) {
$result[$id][] = $data;
} else {
$result[$id] = array($data);
}
}
Best ans.
$levels = array_unique(array_column($records, 'level'));
$data = array();
foreach($records as $key => $value){
$data[$levels[array_search($value['level'],$levels )]][] = $value ;
}
print_r($data);
To generate the question's exact desured output from the sample input, pull/pop the last value from each row, use that value as the first level grouping key. Then use the original first level index as the second level key. Then push the two remaining elements into the group's subset.
Code: (Demo)
$result = [];
foreach ($array as $key => $row) {
$result[array_pop($row)][$key] = $row;
}
var_export($result);
For functional style syntax, use array_reduce(). (Demo)
var_export(
array_reduce(
array_keys($array),
function($result, $key) use ($array) {
$result[array_pop($array[$key])][$key] = $array[$key];
return $result;
}
)
);
function _group_by($array,$key,$keyName)
{
$return = array();
foreach($array as $val) {
$return[$keyName.$val[$key]][] = $val;
}
return $return;
} //end of function
I have a multidimensional array with key and value and some key is empty also. Then I want to set a value for internal not empty array.
$oldArray = array("Lexus LS600" => array(),
"Toyota Alphard" => array(),
"Benz S550" => array(0 => array(
"card_no" => "G2FPCBS3",
"travel_date" => "2020-09-10"
"travel_time" => "16:15:00",
"car_id" => 12,
"return_time" => "17:25")),
"BMW X6" => array());
I had this array but I want to set return_time 00:00 all over array. I tried foreach loop but foreach is remove empty array but I want empty array also.
I want this type array:-
$newArray = array("Lexus LS600" => array(),
"Toyota Alphard" => array(),
"Benz S550" => array(0 => array(
"card_no" => "G2FPCBS3",
"travel_date" => "2020-09-10"
"travel_time" => "16:15:00",
"car_id" => 12,
"return_time" => "00:00")),
"BMW X6" => array());
Try this foreach again, I think it will solve your problem if I understood you correctly.
foreach ($arrays as $key => $values) {
if (is_array($values)) {
if (count($values)) {
foreach ($values as $index => $data) {
$arrays[$key][$index]['return_time'] = "00:00";
}
} else {
$arrays[$key] = $values;
}
}
}
It will change return_time to "00:00" and also retain the empty index to your array.
array_walk_recursive() is very suitable for this.
$oldArray = array("Lexus LS600" => array(),
"Toyota Alphard" => array(),
"Benz S550" => array(0 => array(
"card_no" => "G2FPCBS3",
"travel_date" => "2020-09-10",
"travel_time" => "16:15:00",
"car_id" => 12,
"return_time" => "17:25")),
"BMW X6" => array());
$keySearch = "return_time";
$replaceWith = "00:00";
array_walk_recursive(
$oldArray,
function(&$val,$key) use($keySearch,$replaceWith){
if($key == $keySearch) $val = $replaceWith;
}
);
var_export($oldArray);
Output:
array (
'Lexus LS600' =>
array (
),
'Toyota Alphard' =>
array (
),
'Benz S550' =>
array (
0 =>
array (
'card_no' => 'G2FPCBS3',
'travel_date' => '2020-09-10',
'travel_time' => '16:15:00',
'car_id' => 12,
'return_time' => '00:00',
),
),
'BMW X6' =>
array (
),
)
Use two foreach loops to traverse the limited-depth array and make all values modifiable by reference (& before the variable). In doing so, you don't need to create a separate array, just update the input array. It is SUPER easy to read and maintain.
Code: (Demo)
foreach ($array as &$cars) {
foreach ($cars as &$entry) {
if ($entry) {
$entry["return_time"] = "00:00";
}
}
}
var_export($array);
Output:
array (
'Lexus LS600' =>
array (
),
'Toyota Alphard' =>
array (
),
'Benz S550' =>
array (
0 =>
array (
'card_no' => 'G2FPCBS3',
'travel_date' => '2020-09-10',
'travel_time' => '16:15:00',
'car_id' => 12,
'return_time' => '00:00',
),
),
'BMW X6' =>
array (
),
)
I have 2 arrays that contain user details, including emails addresses. I would like to create a new array that contain only the user details where email that appear in both arrays. is there any function that do that?
I tried to use "array_intersect_assoc". no good...
$newGroupsArray = array_intersect ($firstArray , $secondArray );
for instance, - in this example only "nathalie" details should be in the new array.
Is there any function that do that?
$firstArray = array( 0 => Array ( 'name' => 'ronen', 'email' => 'ronen$Experts.com' , 'contactID' => 43 ) ,
1 => Array ( 'name' => 'shlomig' , 'email' => 'shlomig$tours.co.il' ,'contactID' => 28 ) ,
2 => Array ( 'name' => 'nathalie', 'email' => 'nathalie$obra.co.il', 'contactID' => 57 )
);
$secondArray = array(0 => Array ( 'name' => 'nathalie', 'email' => 'nathalie$obra.co.il', 'contactID' => 57 ) ,
1 => Array ('name' => 'roi' , 'email' => 'roi$mail.com' ,'contactID' => 99 )
);
You can combine array_values and array_intersect_key to get desired result.
$Array1 = array();
$Array2 = array();
foreach ($firstArray as $value)
{
$Array1[$value['email']] = $value;
}
foreach ($secondArray as $value)
{
$Array2[$value['email']] = $value;
}
$matches = array_values(array_intersect_key($Array1, $Array2));
print_r($matches);
You can also use foreach loops and check the data using an if condition as below.
$matches = array();
foreach($firstArray as $key => $value)
{
foreach($secondArray as $value1)
{
if($value['email'] === $value1['email'])
$matches[] = $value;
}
}
print_r($matches);
I want to create a list where if its already in the array to add to the value +1.
Current Output
[1] => Array
(
[source] => 397
[value] => 1
)
[2] => Array
(
[source] => 397
[value] => 1
)
[3] => Array
(
[source] => 1314
[value] => 1
)
What I want to Achieve
[1] => Array
(
[source] => 397
[value] => 2
)
[2] => Array
(
[source] => 1314
[value] => 1
)
My current dulled down PHP
foreach ($submissions as $timefix) {
//Start countng
$data = array(
'source' => $timefix['parent']['id'],
'value' => '1'
);
$dataJson[] = $data;
}
print_r($dataJson);
Simply use an associated array:
$dataJson = array();
foreach ($submissions as $timefix) {
$id = $timefix['parent']['id'];
if (!isset($dataJson[$id])) {
$dataJson[$id] = array('source' => $id, 'value' => 1);
} else {
$dataJson[$id]['value']++;
}
}
$dataJson = array_values($dataJson); // reset the keys - you don't nessesarily need this
This is not exactly your desired output, as the array keys are not preserved, but if it suits you, you could use the item ID as the array key. This would simplify your code to the point of not needing to loop through the already available results:
foreach ($submissions as $timefix) {
$id = $timefix['parent']['id'];
if (array_key_exists($id, $dataJson)) {
$dataJson[$id]["value"]++;
} else {
$dataJson[$id] = [
"source" => $id,
"value" => 1
];
}
}
print_r($dataJson);
You should simplify this for yourself. Something like:
<?
$res = Array();
foreach ($original as $item) {
if (!isset($res[$item['source']])) $res[$item['source']] = $item['value'];
else $res[$item['source']] += $item['value'];
}
?>
After this, you will have array $res which will be something like:
Array(
[397] => 2,
[1314] => 1
)
Then, if you really need the format specified, you can use something like:
<?
$final = Array();
foreach ($res as $source=>$value) $final[] = Array(
'source' => $source,
'value' => $value
);
?>
This code will do the counting and produce a $new array as described in your example.
$data = array(
array('source' => 397, 'value' => 1),
array('source' => 397, 'value' => 1),
array('source' => 1314, 'value' => 1),
);
$new = array();
foreach ($data as $item)
{
$source = $item['source'];
if (isset($new[$source]))
$new[$source]['value'] += $item['value'];
else
$new[$source] = $item;
}
$new = array_values($new);
PHP has a function called array_count_values for that. May be you can use it
Example:
<?php
$array = array(1, "hello", 1, "world", "hello");
print_r(array_count_values($array));
?>
Output:
Array
(
[1] => 2
[hello] => 2
[world] => 1
)
I have a multidimensional array and am trying to group them according to the value in a specific column.
I'm trying to group them by level, but I won't actually know the level beforehand. So, it's not like I can put it in a for loop and say while $i < 7, because I won't know that 7 is the maximum value for the level key, and frankly, I'm not sure that's how I would need to do it even if I did.
[
['cust' => 'XT8900', 'type' => 'standard', 'level' => 1],
['cust' => 'XT8944', 'type' => 'standard', 'level' => 1],
['cust' => 'XT8922', 'type' => 'premier', 'level' => 3],
['cust' => 'XT8816', 'type' => 'permier', 'level' => 3],
['cust' => 'XT7434', 'type' => 'standard', 'level' => 7],
]
Desired result:
Array (
[1] => Array (
[0] => Array (
[cust] => XT8900
[type] => standard
)
[1] => Array (
[cust] => XT8944
[type] => standard
)
)
[3] => Array (
[2] => Array (
[cust] => XT8922
[type] => premier
)
[3] => Array (
[cust] => XT8816
[type] => permier
)
)
[7] => Array (
[4] => Array (
[cust] => XT7434
[type] => standard
)
)
)
Best way, if you have control over building the initial array, is just set things up like that at the start as you add entries.
If not then build a temporary array to sort:
foreach ($input_arr as $key => &$entry) {
$level_arr[$entry['level']][$key] = $entry;
}
Leaves you with the form you wanted and everything referenced together.
Build the array like that in the first place though if at all possible.
You need to group them by level first
Use foreach to loop into array check if the level is the same with the previous item then group it with that array
$templevel=0;
$newkey=0;
$grouparr[$templevel]="";
foreach ($items as $key => $val) {
if ($templevel==$val['level']){
$grouparr[$templevel][$newkey]=$val;
} else {
$grouparr[$val['level']][$newkey]=$val;
}
$newkey++;
}
print($grouparr);
The output of print($grouparr); will display like the format you hoped for
You can also try to
print($grouparr[7]);
Will display
[7] => Array (
[4] => Array (
[cust] => XT7434
[type] => standard
)
)
Or
print($grouparr[3]);
Will display
[3] => Array (
[2] => Array (
[cust] => XT8922
[type] => premier
)
[3] => Array (
[cust] => XT8816
[type] => permier
)
)
Here is the solution I landed on for an identical problem, wrapped as a function:
function arraySort($input,$sortkey){
foreach ($input as $key=>$val) $output[$val[$sortkey]][]=$val;
return $output;
}
To sort $myarray by the key named "level" just do this:
$myArray = arraySort($myArray,'level');
Or if you didn't want it as a function, just for a one time use, this would create $myNewArray from $myArray grouped by the key 'level'
foreach ($myArray as $key=>$val) $myNewArray[$val['level']][]=$val;
function group_assoc($array, $key) {
$return = array();
foreach($array as $v) {
$return[$v[$key]][] = $v;
}
return $return;
}
//Group the requests by their account_id
$account_requests = group_assoc($requests, 'account_id');
$result = array();
foreach ($yourArrayList as $data) {
$id = $data['level'];
if (isset($result[$id])) {
$result[$id][] = $data;
} else {
$result[$id] = array($data);
}
}
Best ans.
$levels = array_unique(array_column($records, 'level'));
$data = array();
foreach($records as $key => $value){
$data[$levels[array_search($value['level'],$levels )]][] = $value ;
}
print_r($data);
To generate the question's exact desured output from the sample input, pull/pop the last value from each row, use that value as the first level grouping key. Then use the original first level index as the second level key. Then push the two remaining elements into the group's subset.
Code: (Demo)
$result = [];
foreach ($array as $key => $row) {
$result[array_pop($row)][$key] = $row;
}
var_export($result);
For functional style syntax, use array_reduce(). (Demo)
var_export(
array_reduce(
array_keys($array),
function($result, $key) use ($array) {
$result[array_pop($array[$key])][$key] = $array[$key];
return $result;
}
)
);
function _group_by($array,$key,$keyName)
{
$return = array();
foreach($array as $val) {
$return[$keyName.$val[$key]][] = $val;
}
return $return;
} //end of function