Convert an array with index and value into an array - php

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

Related

Filter array with array_walk_recursive but deny specific values

I am trying to filter an array
$array = [
[
'id' => 1,
'some_key' => 'some_value',
'attribute' => [
'id' => 45,
'cat_id' => 1
],
'sub' => [
'id' => 17,
'some_key' => 'some_value',
'attribute' => [
'id' => 47,
'cat_id' => 17
],
],
],
[
'id' => 2,
'some_key' => 'some_value',
'sub' => [
'id' => 19,
'some_key' => 'some_value',
],
]
];
$childArray = [];
array_walk_recursive($array, static function($value, $key) use(&$childArray){
if($key === 'id') {
$childArray[] = $value;
}
});
This returns me an array of all array-fields having id as key.
[1,45,17,47,2,19]
But there is a small problem, some of the array have an key called attribute containing an idkey field that I dont want to have.
[1,17,2,19] //this is what I want
Is there a way to say "don't take the id inside attribute" ?
My current solution, I added a filter before my filter :D
/**
* #param array $array
* #param string $unwanted_key
*/
private function recursive_unset(&$array, $unwanted_key)
{
unset($array[$unwanted_key]);
foreach ($array as &$value) {
if (is_array($value)) {
$this->recursive_unset($value, $unwanted_key);
}
}
}
but this seems like this is not the best practice ^^
You can traverse recursively manually instead of array_walk_recursive and avoid all under attribute key.
<?php
$childArray = [];
function collectIDs($arr,&$childArray){
foreach($arr as $key => $value){
if($key === 'attribute') continue;
if(is_array($value)) collectIDs($value,$childArray);
else if($key === 'id') $childArray[] = $value;
}
}
collectIDs($array,$childArray);
print_r($childArray);
Demo: https://3v4l.org/V6uFf
Find a function that will flatten your array. The result should look like this (I have a class for this):
array (
0 =>
array (
'id' => 1,
'some_key' => "some_value",
'attribute.id' => 45,
'attribute.cat_id' => 1,
'sub.id' => 17,
'sub.some_key' => "some_value",
'sub.attribute.id' => 47,
'sub.attribute.cat_id' => 17,
),
1 =>
array (
'id' => 2,
'some_key' => "some_value",
'sub.id' => 19,
'sub.some_key' => "some_value",
),
)
So you have all keys available and can work with a modified array_walk.
$childArray = [];
array_walk_recursive($data, static function($value, $key) use(&$childArray){
$keys = array_reverse(explode(".",$key));
if($keys[0] === 'id' AND (!isset($keys[1]) OR $keys[1] != 'attribute')) {
$childArray[] = $value;
}
});
The RecursiveArrayIterator class is also very suitable when array values ​​are to be collected depending on keys and values ​​on different levels.
$result = [];
$it = new RecursiveIteratorIterator(new RecursiveArrayIterator($array));
foreach($it as $key => $value) {
$parentLevel = $it->getDepth()-1;
$parentKey = $it->getSubIterator($parentLevel)->key();
if($key === 'id' AND $parentKey !== 'attribute'){
$result[] = $value;
}
}
var_export($result);
//array ( 0 => 1, 1 => 17, 2 => 2, 3 => 19, )
To return the qualifying ids instead of creating a reference variable, merge recursive calls of the function as you iterate.
Code: (Demo)
function getIds($array) {
$ids = [];
foreach ($array as $key => $value) {
if ($key === 'id') {
$ids[] = $value;
} elseif ($key !== 'attribute' && is_array($value)) {
$ids = array_merge($ids, getIds($value));
}
}
return $ids;
}
var_export(getIds($array));
Output:
array (
0 => 1,
1 => 17,
2 => 2,
3 => 19,
)

array_walk not working as expected when modifying the values

I am trying to add a new value to the array (I know it is possible with array_map() but I would like to test it with the array_walk()).
This is the code:
$array = [
[
'id' => 1,
'name' => 'Jesus',
],
[
'id' => 2,
'name' => 'David',
],
];
And I want this output:
$array = [
[
'id' => 1,
'name' => 'Jesus',
'locked' => 0,
],
[
'id' => 2,
'name' => 'David',
'locked' => 0,
],
];
I tried with the following code:
array_walk($array, static function(array $item): array {
$item += ['locked' => 0];
//var_dump($item); // Here the array has the three values.
return $item;
});
// Also I tried the same code but not returning the array, I mean:
array_walk($array, static function(array $item): void {
$item += ['locked' => 0];
//var_dump($item); // Here the array has the three values.
});
Is it possible what I want with an array_walk()?
That would be the solution with an array_map().
$arrayMapped = array_map(static function(array $item): array {
return $item += ['locked' => 0];
}, $array);
var_dump($arrayMapped);
Cheers!
Arrays are passed by value. You need to define the argument by reference using &
array_walk($array, function(array &$item): void {
$item['locked'] = 0;
});

Remove unwanted elements from subarrays in multidimensional array

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);

push certain elements into array php

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]

PHP - How to create such array?

The question is simple, I want to create the array below dynamically, but the code I got now only outputs the last row. Is there anybody who knows what is wrong with my dynamically array creation?
$workingArray = [];
$workingArray =
[
0 =>
[
'id' => 1,
'name' => 'Name1',
],
1 =>
[
'id' => 2,
'name' => 'Name2',
]
];
echo json_encode($workingArray);
/* My not working array */
$i = 0;
$code = $_POST['code'];
$dynamicArray = [];
foreach ($Optionsclass->get_options() as $key => $value)
{
if ($value['id'] == $code)
{
$dynamicArray =
[
$i =>
[
'id' => $key,
'name' => $value['options']
]
];
$i++;
}
}
echo json_encode($dynamicArray);
You dont need to have the $i stuff that is adding another level to your array that you dont want.
$code = $_POST['code'];
$dynamicArray = [];
foreach ($Optionsclass->get_options() as $key => $value)
{
if ($value['id'] == $code)
{
$dynamicArray[] = ['id' => $key, 'name' => $value['options'];
}
}
echo json_encode($dynamicArray);
You are creating a new dynamic array at each iteration:
$dynamicArray =
[
$i =>
[
'id' => $key,
'name' => $value['options']
]
];
Instead, declare $dynamicArray = []; above the foreach, and then use:
array_push($dynamicArray, [ 'id' => $key, 'name' => $value['options']);
inside the array.

Categories