I want to know that is there a way to insert certain elements of an array into a new array. I mean I have an array containing 10 objects. Each object has 3 or four fields for example id, name , age , username. now I want to insert the id's of all the objects into the new array with a single call.Is there anyway to do that.
$array = [
[0] => [
id =>
name =>
],
[1] = > [
id =>
name =>
]
]
and so on now I want to insert all the id's of all the object into a new array with a single call. Is there a way to do that?
Use array_map() function.
Here is your solution:-
$ids = array_map( function( $arr ){
return $arr["id"];
}, $arr );
echo '<pre>'; print_r($ids);
A basic foreach loop will do the job just fine
$firstArray = array(
array(
'id' => 1,
'name' => 'abc'
),
array(
'id' => 2,
'name' => 'def'
),
array(
'id' => 3,
'name' => 'gh'
)
);
$onlyIds = array();
$onlyKeys = array();
//To get the array value 'id'
foreach($firstArray as $value){
$onlyIds[] = $value['id'];
}
//To get the array keys
foreach($firstArray as $key => $value){
$onlyKeys[] = $key;
}
You could use array_walk which could be considered a "single call"
$array = array(0 => array('id', 'name', 'age'), 1 => array('id', 'name', 'age'));
array_walk($array, function($item, $key) {
// $key is 0 or 1
// $item is either id, name, age
});
You can use array_column.
$arr = [ ['id' => 1, 'username' => 'a'], ['id' => 2, 'username' => 'b'] ];
$ids = array_column($arr, 'id')
$ids == [1, 2]
Related
I have an array like so:
$array = [
['record' => 1, 'sponsor' => 2, 'email' => 'some#email.com'],
['record' => 2, 'sponsor' => 2, 'email' => 'some1#email.com'],
['record' => 3, 'sponsor' => 2, 'email' => 'some2#email.com'],
['record' => 4, 'sponsor' => 2, 'email' => 'some3#email.com'],
];
Each row has a unique record and email and the sponsor key is related to the record. So, instead of an integer, I am trying to replace the value of the sponsor key with the corresponding email based on the record, something like this:
$array = [
['record' => 1, 'sponsor' => 'some1#email.com', 'email' => 'some#email.com'],
['record' => 2, 'sponsor' => 'some1#email.com', 'email' => 'some1#email.com'],
['record' => 3, 'sponsor' => 'some1#email.com', 'email' => 'some2#email.com'],
['record' => 4, 'sponsor' => 'some1#email.com', 'email' => 'some3#email.com'],
];
I have tried using a foreach loop but it doesn't give me the expected result:
$yes = [];
foreach ($array as $key => $arr) {
if ( ! empty($arr['sponsor']) ) {
if ( $arr['sponsor'] == $array[$key]['record'] ) {
$yes[] = ['sponsor' => $array[$key]['email']];
}
}
$yes[] = [
'record' => $array[$key]['record'],
'email' => $array[$key]['email'],
'sponsor' => $array[$key]['sponsor'],
];
}
print_r($yes);
As record is unique, I recommend rebuilding $arr using this value as the key. Then you loop again to replace your value for $sponsor –
$indexedArray = [];
foreach ($array as $v) {
$indexedArray[$v['record']] = $v;
}
foreach ($indexedArray as $record => $v) {
if (isset($indexedArray[$v['sponsor']]) && isset($indexedArray[$v['sponsor']]['email'])) {
$indexedArray[$record]['sponsor'] = $indexedArray[$v['sponsor']]['email'];
}
}
$yes = array_values($indexedArray);
Create a lookup array with record values as keys and email values as values, then overwrite the sponsor value in each row based on the corresponding lookup value.
Code: (Demo)
$lookup = array_column($array, 'email', 'record');
var_export(
array_map(fn($row) => array_replace($row, ['sponsor' => $lookup[$row['sponsor']]]), $array)
);
Or with a classic loop: (Demo)
$lookup = array_column($array, 'email', 'record');
foreach ($array as &$row) {
$row['sponsor'] = $lookup[$row['sponsor']];
}
var_export($array);
If there is a chance that a given sponsor value might not be found in the lookup, then use $lookup[$row['sponsor']] ?? 'some fallback' when you try to access the lookup array. This way you will not generate warnings/errors. This is a more concise way of checking isset().
p.s. Bear in mind that using the array union operator won't work properly in this case.
I have a multidimensional array like this:
[
[
'id' => 1,
'name' => 'John',
'address' => 'Some address 1'
'city' => 'NY'
],
[
'id' => 2,
'name' => 'Jack',
'address' => 'Some address 2'
'city' => 'NY'
]
...
[ ... ]
]
How can I remove elements in all subarrays and only retain the id and name keys with their values?
Would this work?
$result = array_map(function($arr) {
return [
'id' => $arr['id'],
'name' => $arr['name']
];
}, $orig_array);
You want to retain the first two associative elements, so you can make array_slice() calls within array_map(). (Demo)
var_export(
array_map(fn($row) => array_slice($row, 0, 2), $array)
);
Or mapped called of array_intersect_key() against an establish whitelist array. (Demo)
$keep = ['id' => '', 'name' => ''];
var_export(
array_map(
fn($row) => array_intersect_key($row, $keep),
$array
)
)
Or, you could use array destructuring inside of a classic foreach() and make iterated compact() calls. (Demo)
$result = [];
foreach ($array as ['id' => $id, 'name' => $name]) {
$result[] = compact(['id', 'name']);
}
var_export($result);
If you want to edit the same array in place, you can simply iterate over them and unset them.
<?php
$preserve_keys = ['id','name'];
foreach($arr as &$data){
foreach($data as $key => $value){
if(!in_array($key,$preserve_keys)){
unset($data[$key]);
}
}
}
If you want it as a separate result, loop over and add it to the new array.
<?php
$new_result = [];
foreach($arr as $data){
$new_result[] = [
'id' => $data['id'],
'name' => $data['name']
];
}
print_r($new_result);
I have an array as key => value pair such as:
$array = [ 10 => 'Windows', 12 => 'Keyboard', 15 => 'Monitor' ];
What I would like to achieve without using any foreach or loops the following:
$converted = [
0 => [ 'id' => 10, 'name' => 'Windows'],
1 => [ 'id' => 12, 'name' => 'Keyboard'],
2 => [ 'id' => 15, 'name' => 'Monitor']
];
Here they indices in new array doesn't matter. Any tips??
No foreach and no loop, but now there is a closure:
$result = array_map(function ($id, $name) {
return [
'id' => $id,
'name' => $name
];
}, array_keys($array), array_values($array));
Even if there was a PHP function that did this exactly, it would be using a loop internally.
function do_what_ghazanfar_mir_wants(array $array) {
return array_map(function ($id, $name) {
return [
'id' => $id,
'name' => $name
];
}, array_keys($array), array_values($array));
}
And the single liner is:
$result = do_what_ghazanfar_mir_wants($array);
And the foreach approach for comparison:
$res = [];
foreach ($array as $id => $name) {
$res[] = [ 'id' => $id, 'name' => $name ];
}
If you want to keep it really short then array_walk will do it in one line:
array_walk($array, function(&$value, $key) { $value = ['id' => $key, 'name' => $value]; });
See https://3v4l.org/OEohi
But I think a foreach loop is probably going to be a lot more readable.
Do it with array_map(), Just pass the keys array_keys($array) and values $array as the parameter of your array_map()
<?php
$array = [ 10 => 'Windows', 12 => 'Keyboard', 15 => 'Monitor' ];
function map_by_key($m, $n)
{
return(array('id' => $m, 'name'=>$n));
}
$output = array_map("map_by_key", array_keys($array),$array);
print '<pre>';
print_r($output);
print '</pre>';
?>
DEMO: https://3v4l.org/iTVSm
I have the following array that includes id:
[Key1] => 1
[Key2] => 2, 3
I would like to replace these ids by their respective name from this second array:
[0] => Array
(
[ID] => 1
[Name] => Name1
)
[1] => Array
(
[ID] => 2
[Name] => Name2
)
[2] => Array
(
[ID] => 3
[Name] => Name3
The desired output:
[Key1] => Name1
[Key2] => Name2, Name3
I have the following code which works but I know this is not the right way. If anybody could let me know what would be a better way to achieve this, it would be greatly appreciated.
What my code looks like:
$var1 = explode(", ", $array1["Key1"]); // No need to explode in this example but "Key1" sometimes includes more than 1 ID
$var2 = explode(", ", $array1["Key2"]);
$array1["Key1"] = $var1 ; // This row is for the new array generated from "explode" to be a sub-array
$array1["Key2"] = $var2 ; // Same
for ($i = 0; $i < 83; $i++){
if($array1["Key1"][0] == $array2[$i]["ID"]){
$array1["Key1"][0] = $array2[$i]["Name"];
}
if($array1["Key1"][1] == $array2[$i]["ID"]){
$array1["Key1"][1] = $array2[$i]["Name"];
}
// (etc)
if($array1["Key2"][0] == $array2[$i]["ID"]){
$array1["Key2"][0] = $array2[$i]["Name"];
}
if($array1["Key2"][1] == $array2[$i]["ID"]){
$array1["Key2"][1] = $array2[$i]["Name"];
}
// (etc)
}
$var1 = implode(", ", $array1["Key1"]);
$var2 = implode(", ", $array1["Key2"]);
$array1["Key1"] = $var1 ;
$array1["Key2"] = $var2 ;
Just extract the ID and Name into a single-dimension and use it as search and replace parameters. We need to modify the IDs to search for and turn them into a pattern /\b$v\b/ where \b is a word boundary, so that 1 won't replace the 1 in 164 for example:
$replace = array_column($array2, 'Name', 'ID');
$search = array_map(function($v) { return "/\b$v\b/"; }, array_keys($replace));
$array1 = preg_replace($search, $replace, $array1);
You need to nest some loops. Here is a sample that should work:
//Processing Array
$arrayOne = array(
"Key1" => "1",
"Key2" => "2, 3");
//Lookup Array
$arrayTwo = array(
array(
"ID" => "1",
"Name" => "Name1"),
array(
"ID" => "2",
"Name" => "Name2"),
array(
"ID" => "3",
"Name" => "Name3"));
var_dump($arrayOne);
//Loop through all values in our original array
foreach($arrayOne as &$arrValue) {
//Split the value in the original array into another temporary array
//if there are multiple values.
$valueArray = explode(", ", $arrValue);
$outputArray = array();
foreach($valueArray as &$myValue) {
//Now do a lookup to replace each value
foreach($arrayTwo as &$lookupValue) {
//Find a match
if($myValue==$lookupValue["ID"]) {
$myValue = $lookupValue["Name"];
//We found the value we want, so let's break out of this loop
break;
}
}
//Append the value
array_push($outputArray, $myValue);
}
//Convert back to string
$arrValue= implode(", ", $outputArray);
}
var_dump($arrayOne);
There are improvements you could possibly make to this code if your incoming data was always sorted, but I imagine that is just the case for your sample above.
I have an approach to do this. You can make a try if you wish see here at:- https://eval.in/839823. I am using array_column to map the key=>value pair and then simple used foreach.
<?php
$main = ['Key1' => 1,'Key2' => '2, 3'];
$match = [
[
'ID' => 1,
'Name' => 'Name1'
],
[
'ID' => 2,
'Name' => 'Name2'
],
[
'ID' => 3,
'Name' => 'Name3'
]
];
$final_array=[];
$mapped = array_column($match, 'Name', 'ID');
foreach($main as $k=>$v){
$r = explode(',',$v);
if(count($r)>1){
$final_array[$k] = $mapped[$r[0]]. ", ".$mapped[intval($r[1])];
}else{
$final_array[$k] = $mapped[$r[0]];
}
}
print '<pre>';
//print_r($mapped);
print_r($final_array);
print '</pre>';
Output :
Array
(
[Key1] => Name1
[Key2] => Name2,Name3
)
Edit : As per comment of Josh Maag,
My code will only work if he only has a maximum of 2 values in Key2.
If Key3 contains "4,5,6" this code will leave the 6 untouched.
<?php
$main = ['Key1' => 1,'Key2' => '2,3','Key3' => '4,5,6'];
$match = [
[
'ID' => 1,
'Name' => 'Name1'
],
[
'ID' => 2,
'Name' => 'Name2'
],
[
'ID' => 3,
'Name' => 'Name3'
],
[
'ID' => 4,
'Name' => 'Name4'
],
[
'ID' => 5,
'Name' => 'Name5'
],
[
'ID' => 6,
'Name' => 'Name6'
]
];
$final_array=[];
$mapped = array_column($match, 'Name', 'ID');
foreach($main as $k=>$v){
$r = explode(',',$v);
if(count($r)>1){
$final_array[$k] = implode(',',array_map(function($key) use ($mapped){ return $mapped[$key]; }, array_values($r)));
}else{
$final_array[$k] = $mapped[$r[0]];
}
}
print '<pre>';
print_r($mapped);
print_r($final_array);
print '</pre>';
?>
See demo See here https://eval.in/839939
The core function that should be used for this task is preg_replace_callback(). Why? Because it is uniquely qualified to handle this operation in a single function call. It seems a tragedy to not use php functions for their designed purpose.
Beyond preg_replace_callback(), only array_column() is needed to prepare the $array2 data as a simple lookup array.
Code: (Demo)
$array1=["Key1"=>"1","Key2"=>"22, 4, 123"];
$array2=[["ID"=>"1","Name"=>"Name1"],["ID"=>"22","Name"=>"Name22"],["ID"=>"123","Name"=>"Name123"]];
$lookup=array_column($array2,'Name','ID'); // generate array: keys = IDs, vals = Names
$result=preg_replace_callback('/\d+/',function($m)use($lookup){return isset($lookup[$m[0]])?$lookup[$m[0]]:"*{$m[0]}*";},$array1);
var_export($result);
Output:
array (
'Key1' => 'Name1',
'Key2' => 'Name22, **4**, Name123',
)
There is no need to run any preparations (excluding $lookup) using additional loops or function calls.
This pattern will match all full ID numbers from each element in $array1 and process them individual. Each numeric match is sent to the anonymous callback function to receive its customized replacement string -- delivered by the $lookup data.
As an additional consideration, I have included an asterisk-wrapped replacement when an ID is not found in $lookup.
I want to convert this:
$arr = [
[
'type' => 'fruit',
'name' => 'apple',
'cost' => 1
],
[
'type' => 'fruit',
'name' => 'orange',
'cost' => 2
],
[
'type' => 'vegetable',
'name' => 'carrot',
'cost' => 2.5
],
[
'type' => 'vegetable',
'name' => 'avocado',
'cost' => 3.5
]
];
Into this:
$arr = [
[
'type' => 'fruit',
'apple' => '1',
'orange' => 2
],
[
'type' => 'vegetable',
'carrot' => 2.5,
'avocado' => 3.5
]
];
As you can see, I'm needing to group each type in a single array and pivoting fruit name and cost.
Here's a method for obtaining that exact array structure in the output. This was a touch trickier than I thought it would be:
//first build groups by type
$groups = array();
foreach($arr as $key => $array){
//$type is not necessary, it's just for clarity below
$type = $array['type'];
if( !isset($groups[$type]) ){
$groups[$type] = array();
$groups[$type]['type'] = $array['type'];
}
$groups[$type][$array['name']] = $array['cost'];
}
//then combine the groups into a master array
$out = array();
foreach($groups as $g){
$out[] = $g;
}
echo '<pre>'. print_r($out, true).'</pre>';
For something like this simply looping through your array as Rizier suggests should do the trick. If you're grouping by type, it would probably be easiest to use the type as the array key, so the format would be slightly different than you've requested. You'd be able access your resulting array like this:
$fruitItems = $newArr['fruit'];
Here's sample code:
$size = count($itemArray);
$newArr = []; //The array you want to create
for ($i = 0; $i < $size; $i++)
{
$item = $itemArray[$i];
$type = $item['type'];
$name = $item['name'];
$cost = $item['cost']
//If your new array doesn't have this type yet, make a sub-array
//with the type as key
if (!isset($newArr[$type]))
$newArr[$type] = [];
$newArr[$type][$name] = $cost; //In your type sub-array, add the new item
}
If you absolutely have to create an array with that structure, you can tweak the above code a little bit to search through your array and find the sub-array with the correct type. However, that seems a little over complicated.
In case someone needs a little more generic approch and has to handle multiple values in the same column I enlarged #larsAnders solution a bit.
Usage (to get the exact required output):
$pivot_fruits = arr_pivot($arr, 'type', 'name', 'cost', 'sum', false, false);
Function:
function arr_pivot(
$arr,
$arr_key_to_pivot_for_rows,
$arr_key_to_pivot_for_columns,
$arr_key_to_pivot_for_values,
$grouping_method = "sum",
$add_missing_columns=true,
$sort_columns=true){
if(!is_array($arr)) return false;
$pivot_row = $arr_key_to_pivot_for_rows;
$pivot_col = $arr_key_to_pivot_for_columns;
$pivot_val = $arr_key_to_pivot_for_values;
//first build groups by $col_name_to_pivot_for_rows
$row_groups = [];
$columns=[];
foreach ($arr as $row_key => $row) {
$group_label = $row[$pivot_row];
$col_label = $row[$pivot_col];
$value = $row[$pivot_val];
if( !isset($row_groups[$group_label]) ){
$row_groups[$group_label]=[];
$row_groups[$group_label][$pivot_row] = $group_label;
}
if(!isset($columns[$col_label])) $columns[$col_label]=[];
$row_groups[$group_label][$col_label][]=$value;
}
//then combine the groups into a return array
$arr_pivoted = [];
foreach($row_groups as $row_group){
//all columns except of the first one are pivoted columns. split into the row name and the columns itself
$row_group_columns = $row_group;
$row_group_row = array_shift($row_group_columns);
//ensure that all groups have all columns
if($add_missing_columns) $row_group_columns = array_merge($columns,$row_group_columns);
if($sort_columns) ksort($row_group_columns);
$row_group_columns_grouped=[];
//apply grouping function to columns
foreach ($row_group_columns as $column_name => $row_group_column){
$acount=count($row_group_column);
switch ($grouping_method){
default:
case 'sum':
$row_group_columns_grouped[$column_name] = array_sum($row_group_column);
break;
case 'avg':
$row_group_columns_grouped[$column_name] = $acount == 0 ? 0 : array_sum($row_group_column) / count($row_group_column);
break;
case 'count':
$row_group_columns_grouped[$column_name] = count($row_group_column);
break;
case 'max':
$row_group_columns_grouped[$column_name] = $acount == 0 ? 0 : max($row_group_column);
break;
case 'min':
$row_group_columns_grouped[$column_name] = $acount == 0 ? 0 : min($row_group_column);
break;
case 'concat':
case 'implode':
$row_group_columns_grouped[$column_name] = implode(',',$row_group_column);
break;
}
}
$arr_pivoted[] = array_merge([$pivot_row=>$row_group_row],$row_group_columns_grouped);
}
return $arr_pivoted;
}
PHPDoc:
/**
* Turns 2 dimensional array in a pivoted version
*
* #param array $arr 2 dimensional to pivot
* #param string $arr_key_to_pivot_for_rows input array key to use as rows
* #param string $arr_key_to_pivot_for_columns input array key to use as columns
* #param string $arr_key_to_pivot_for_values input array key to use as values
* #param string $grouping_method method to use on values out of sum|count|avg|min|max|concat. If values are not numeric use count or concat
* #param bool $add_missing_columns if true all occurring columns in any row are added if missing
* #param bool $sort_columns if true all columns will be sorted by column name (=key)
* #return array|bool false if input is not an array otherwise the pivoted result as 2 dimensional array
*/
If someone feels the urge to improve coding style, input validation and/or variable naming I would be very glad.
This task is as simple as grouping related data using temporary first level keys.
$array = [
['type' => 'fruit', 'name' => 'apple', 'cost' => 1],
['type' => 'fruit', 'name' => 'orange', 'cost' => 2],
['type' => 'vegetable', 'name' => 'carrot', 'cost' => 2.5],
['type' => 'vegetable', 'name' => 'avocado', 'cost' => 3.5]
];
$result = [];
foreach ($array as $row) {
$result[$row['type']]['type'] = $row['type'];
$result[$row['type']][$row['name']] = $row['cost'];
}
var_export(array_values($result));
Contrary to what is demonstrated by other answers on this page, parent elements do not need to be instantiated/declared before assigning a child element. (The same cannot be said for when assigning child properties in an object.) There is also no need for conditions or multiple loops for this basic task.
Output:
array (
0 =>
array (
'type' => 'fruit',
'apple' => 1,
'orange' => 2,
),
1 =>
array (
'type' => 'vegetable',
'carrot' => 2.5,
'avocado' => 3.5,
),
)
You can also abuse a body-less foreach() loop's destructuring syntax to perform the pivot. (Demo)
$array = [
['type' => 'fruit', 'name' => 'apple', 'cost' => 1],
['type' => 'fruit', 'name' => 'orange', 'cost' => 2],
['type' => 'vegetable', 'name' => 'carrot', 'cost' => 2.5],
['type' => 'vegetable', 'name' => 'avocado', 'cost' => 3.5]
];
$result = [];
foreach ($array as ['type' => $type, 'type' => $result[$type]['type'], 'name' => $name, 'cost' => $result[$type][$name]]);
var_export(array_values($result));
This provides the same result as above. Notice how the type key is written twice while destructuring -- it looks invalid, but it actually works.