How to use array values as keys without loops? [duplicate] - php

This question already has answers here:
Generate an associative array from an array of rows using one column as keys and another column as values
(3 answers)
Closed 7 months ago.
Looping is time consuming, we all know that. That's exactly something I'm trying to avoid, even though it's on a small scale. Every bit helps. Well, if it's unset of course :)
On to the issue
I've got an array:
array(3) {
'0' => array(2) {
'id' => 1234,
'name' => 'blablabla',
},
'1' => array(2) {
'id' => 1235,
'name' => 'ababkjkj',
},
'2' => array(2) {
'id' => 1236,
'name' => 'xyzxyzxyz',
},
}
What I'm trying to do is to convert this array as follows:
array(3) {
'1234' => 'blablabla',
'1235' => 'asdkjrker',
'1236' => 'xyzxyzxyz',
}
I guess this aint a hard thing to do but my mind is busted right now and I can't think of anything except for looping to get this done.

Simply use array_combine along with the array_column as
array_combine(array_column($array,'id'), array_column($array,'name'));
Or you can simply use array_walk if you have PHP < 5.5 as
$result = array();
array_walk($array, function($v)use(&$result) {
$result[$v['id']] = $v['name'];
});
Edited:
For future user who has PHP > 5.5 can simply use array_column as
array_column($array,'name','id');
Fiddle(array_walk)

UPD: Warning the slowest solution! See benchmarks below.
Try this code:
$a = array(array('id' => 1234,
'name' => 'blablabla'),
array('id' => 1235,
'name' => 'ababkjkj'),
array('id' => 1236,
'name' => 'xyzxyzxyz'));
var_export(array_reduce($a, function($res, $item) {
$res[$item['id']] = $item['name'];
return $res;
}));
Works fine even in PHP 5.3. And uses only one function array_reduce.
UPD:
Here are some benchmarks (PHP 5.6 over Debian 7 on a medium quality server):
$a = [];
for ($i = 0; $i < 150000; $i++) {
$a[$i] = ['id' => $i,
'name' => str_shuffle('abcde') . str_shuffle('01234')];
}
$start = microtime(true);
if (false) {
// 7.7489550113678 secs for 15 000 itmes
$r = array_reduce($a, function($res, $item) {
$res[$item['id']] = $item['name'];
return $res;
});
}
if (false) {
// 0.096649885177612 secs for 150 000 items
$r = array_combine(array_column($a, 'id'),
array_column($a, 'name'));
}
if (true) {
// 0.066264867782593 secs for 150 000 items
$r = [];
foreach ($a as $subarray) {
$r[$subarray['id']] = $subarray['name'];
}
}
if (false) {
// 0.32427287101746 secs for 150 000 items
$r = [];
array_walk($a, function($v) use (&$r) {
$r[$v['id']] = $v['name'];
});
}
echo (microtime(true) - $start) . ' secs' . PHP_EOL;
So, as a conclusion: plain iteration with simple for loop is a winner (as mentioned in this answer). On a second place there is array_combine allowed only for new versions of PHP. And the worst case is using my own solution with closure and array_reduce.

If you have php >= 5.5:
$res = array_combine(array_column($source, 'id'), array_column($source, 'name'));
If not - make a loop.

Make use of array_map function, (PHP 4 >= 4.0.6, PHP 5)
[akshay#localhost tmp]$ cat test.php
<?php
$array = array(
array('id' => 1234,'name' => 'blablabla'),
array('id' => 1235,'name' => 'ababkjkj'),
array('id' => 1236,'name' => 'xyzxyzxyz')
);
$output = array();
array_map(function($_) use (&$output){ $output[$_['id']] = $_['name']; },$array);
// Input
print_r($array);
// Output
print_r($output);
?>
Output
[akshay#localhost tmp]$ php test.php
Array
(
[0] => Array
(
[id] => 1234
[name] => blablabla
)
[1] => Array
(
[id] => 1235
[name] => ababkjkj
)
[2] => Array
(
[id] => 1236
[name] => xyzxyzxyz
)
)
Array
(
[1234] => blablabla
[1235] => ababkjkj
[1236] => xyzxyzxyz
)

This is the fastest and simplest code here so far ...
$result = [];
foreach ($input as $subarray) {
$result[$subarray["id"]] = $subarray["name"];
}

Try this function:
array_combine(array_column($array,'id'), array_column($array,'name'));

Related

how to get maximum value from array php

How can I get the maximum distance from the array below? I am getting the following output when i try to print_r($data):
Array
(
[0] => Array
(
[distance] => 1.7 km
[time] => 3 mins
[distance_value] => 1720
[time_value] => 192
)
[1] => Array
(
[distance] => 4.2 km
[time] => 10 mins
[distance_value] => 4207
[time_value] => 587
)
)
I want to echo 4.2 km because it is the max distance in my array.
foreach ($delivery as $key => $value) {
if($key==0) {
$mysource = $pickup;
} else {
$mysource = $delivery[$key-1];
}
$data[$key] = $this->GetDrivingDistance($mysource,$value);
if(!empty($data[$key])) {
$dist += max($data[$key]['distance']);
}
}
echo $dist; exit();
print_r($data); exit();
You can make use of built-in functions:
echo max(array_map('floatval',array_column($array, "distance")))." km";
Explanation:
array_column - converts your array to single dimensional
array_map - Apply float operation to the string. This is important since your string comparison compares two numbers wrongly. When float function is applied your km will be removed, so append later on.
Example for string:
11.7 is less than 4.2, because it compares first character and arranges by 1,2,3...
Output:
4.2 km
Note:
This is suitable if all values are in km,if it is in other units, you need a workaround too!
<?php
$array = array
(
array
(
"distance" => "1.7 km",
"time" => "3 mins",
"distance_value" => 1720,
"time_value" => 192,
),
array
(
"distance" => "4.2 km",
"time" => "10 mins",
"distance_value" => 4207,
"time_value" => 587,
)
);
$distance = [];
$i = 0;
foreach ($array as $distance_data) {
$distance[] = (float)$distance_data["distance"];
$i++;
}
$max_distnace = max($distance);
var_dump($max_distnace);
You can first sort the array by distance and get the required one:
$myArray =
array (
array
(
'distance' => '1.7 km',
'time' => '3 mins',
'distance_value' => 1720,
'time_value' => 192,
),
array
(
'distance' => '4.2 km',
'time' => '10 mins',
'distance_value' => 4207,
'time_value' => 587,
)
);
usort($myArray,function($a, $b) {
return $b['distance_value'] - $a['distance_value'];
});
$maxDistance = $myArray[0];
echo $maxDistance['distance'];
// 4.2 km
I get solution from below code..
foreach ($delivery as $key => $value) {
if($key==0){
$mysource = $pickup;
}else{
$mysource = $delivery[$key-1];
}
$data[$key] = $this->GetDrivingDistance($mysource,$value);
if(!empty($data[$key])){
$max = '-9999999 km'; //will hold max val
$found_item = null; //will hold item with max val;
foreach($data as $k=>$v)
{
if($v['distance']>$max)
{
$max = $v['distance'];
$found_item = $v;
}
}
}
}
$dist = $max;
Thamilan's answer is the best, but as you're using CakePHP you can also use Hash::extract() if array_column() isn't available to you (i.e. you're using an older version of PHP) or if you need to use an array with deeper associations thanks to the Hash utility's path syntax:-
echo max(array_map('floatval', Hash::extract($array, 'distance'))) . ' km';
Here Hash::extract() is working like array_column() and converting your array to a single dimensional array.
Sine this questions is tagged with CakePHP I though I'd give my solution using CakePHP Collection class:
use Cake\Collection\Collection;
(new Collection($data))->sortBy('distance_value')->first()['distance'];
Note that CakePHP has a utility function collection that can make this shorter:
collection($data)->sortBy('distance_value')->first()['distance']

PHP Find a value in a key and get the value of another key in a multi-dimentional array

Might be a newbie question but I've been trying to figure this problem and it's doing my head in.
I have the following array :
[0] => Array
(
[provisionalBookingRoomID] => 1
[totalSpecificRoomCount] => 2
)
[1] => Array
(
[provisionalBookingRoomID] => 2
[totalSpecificRoomCount] => 5
)
I need a php function that searches through the array for the value of 'provisionalBookingRoomID' and returns the value of 'totalSpecificRoomCount'
basically something like the following
getProvisionalTotalRoomsCount($currentRoom, $arrayOfRooms);
// getProvisionalTotalRoomsCount('1', $arrayOfRooms) should return 2;
Any ideas?
Check this:
getProvisionalTotalRoomsCount($currentRoom, $arrayOfRooms){
foreach($arrayOfRooms as $key=>$value){
if($value['provisionalBookingRoomID'] == $currentRoom){
return $value['totalSpecificRoomCount'];
}
}
}
For anyone looking for a generic function :
function findValueInArray($array, $searchValue, $searchKey, $requiredKeyValue) {
foreach($array as $key=>$value){
if($value[$searchKey] == $searchValue){
return $value[$requiredKeyValue];
}
}
}
// Usage : findValueInArray($provisionalBookedRoomsArray, '1', 'provisionalBookingRoomID', 'totalSpecificRoomCount');
If you are likely to work with more than one value, you could build a new array with a 1->1 map for those attributes.
<?php
$items = array(
array(
'name' => 'Foo',
'age' => 23
),
array(
'name' => 'Bar',
'age' => 47
)
);
// Php 7
$name_ages = array_column($items, 'name', 'age');
echo $name_ages['Foo']; // Output 23
// Earlier versions:
$name_ages = array();
foreach($items as $value)
{
$name_ages[$value['name']] = $value['age'];
}
echo $name_ages['Foo']; // Output 23
$value = 0;
$array = array(array("provisionalBookingRoomID"=>1,"totalSpecificRoomCount"=>2),array("provisionalBookingRoomID"=>2,"totalSpecificRoomCount"=>5));
array_map(
function($arr) use (&$value) {
if($arr['provisionalBookingRoomID']==1) {
$value = $arr['totalSpecificRoomCount'];
}
},$array
);
echo $value;

How to merge arrays with same key and different value in PHP?

I have arrays similarly to these:
0 => Array ( [0] => Finance / Shopping / Food, [1] => 47 )
1 => Array ( [0] => Finance / Shopping / Food, [1] => 25 )
2 => Array ( [0] => Finance / Shopping / Electronic, [1] => 190 )
I need to create one array with [0] as a key and [1] as value.
The tricky part is that if the [0] is same it add [1] to existing value.
So the result I want is:
array ([Finance / Shopping / Food]=> 72, [Finance / Shopping / Electronic] => 190);
thanks
// array array_merge_values($base[, $merge[, ...]])
// Combines multiple array values based on key
// (adding them together instead of the native array_merge using append)
//
// $base - array to start off with
// $merge[...] - additional array(s) to include (and add their values) on to the base
function array_merge_values()
{
$args = func_get_args();
$result = $args[0];
for ($_ = 1; $_ < count($args); $_++)
foreach ($args[$_] as $key => $value)
{
if (array_key_exists($key,$result))
$result[$key] += $value;
else
$result[$key] = $value;
}
return $result;
}
$array1 = Array('foo' => 5, 'bar' => 10, 'foobar' => 15);
$array2 = Array('foo' => 20, 'foohbah' => 25);
$array3 = Array( 'bar' => 30);
var_dump(array_merge_values($array1,$array2,$array3));
Result:
array(4) {
["foo"]=>
int(25)
["bar"]=>
int(40)
["foobar"]=>
int(15)
["foohbah"]=>
int(25)
}
That what you're looking for?
This should work:
$outArray = array()
foreach($superArray as $subArray) {
if(array_key_exists($outArray,$subArray[0])) {
$outArray[$subArray[0]] += $subArray[1];
} else {
$outArray[$subArray[0]] = $subArray[1];
}
}
Well I don't know how big that array is or what a factor performance is. But this is very specific and I dare to recommend the naive straight forward procedural approach:
<?
$result = array();
foreach($arr as $a) {
$result[$a[0]] += $result[$a[1]];
}
?>
this will generate some php warning, because the field isnt set yet so you probably need to do something like check if the key exists and if not set it the value, and if it is, add the value...
edit: well lets post this, this could look like
<?
$result = array();
foreach($arr as $a) {
if(isset($result[$a[0]])) {
$result[$a[0]] += $result[$a[1]];
} else {
$result[$a[0]] = $result[$a[1]];
}
}
?>
You can use the "+" operand for the purpose.
$arr1 = array(
'key' => '1',
);
$arr2 = array(
'key' => '2',
);
die(var_dump($arr2 + $arr1));
RESULT:
array
'key' => string '2' (length=1)

Create array of hierarchical directories in PHP

I have the following code (I know that this code is not optimized but it's not for discussion):
function select_categories($cat_id)
{
$this->db = ORM::factory('category')
->where('parent', '=', $cat_id)
->find_all();
foreach ($this->db as $num => $category)
{
if($category->parent == 0)
{
$this->tmp[$category->parent][$category->id] = array();
}
else {
$this->tmp[$category->parent][$category->id] = array();
}
$this->select_categories($category->id);
}
return $this->tmp;
}
Function returns this array:
array(3) (
0 => array(2) (
1 => array(0)
2 => array(0)
)
2 => array(1) (
3 => array(0)
)
3 => array(2) (
4 => array(0)
5 => array(0)
)
)
But how should I change the code
else {
$this->tmp[$category->parent][$category->id] = array();
// ^^^^^^^^^^^^^^^^^^^^^^ (this bit)
}
To merge array[3] to array[2][3] for example (because array[3] is a subdirectory of array[2] and array[2] is a subdirectory of array[0][2]), so, I need to make this (when I don't know the level of subdirectories):
array (
0 => array (
1 => array
2 => array (
3 => array (
4 => array
5 => array
)
)
)
)
A long time ago I wrote some code to do this in PHP. It takes a list of entities (in your case, categories) and returns a structure where those entities are arranged in a tree. However, it uses associative arrays instead of objects; it assumes that the “parent” ID is stored in one of the associative array entries. I’m sure that you can adapt this to your needs.
function make_tree_structure ($nontree, $parent_field)
{
$parent_to_children = array();
$root_elements = array();
foreach ($nontree as $id => $elem) {
if (array_key_exists ($elem[$parent_field], $nontree))
$parent_to_children [ $elem[$parent_field] ][] = $id;
else
$root_elements[] = $id;
}
$result = array();
while (count ($root_elements)) {
$id = array_shift ($root_elements);
$result [ $id ] = make_tree_structure_recurse ($id, $parent_to_children, $nontree);
}
return $result;
}
function make_tree_structure_recurse ($id, &$parent_to_children, &$nontree)
{
$ret = $nontree [ $id ];
if (array_key_exists ($id, $parent_to_children)) {
$list_of_children = $parent_to_children [ $id ];
unset ($parent_to_children[$id]);
while (count ($list_of_children)) {
$child = array_shift ($list_of_children);
$ret['children'][$child] = make_tree_structure_recurse ($child, $parent_to_children, $nontree);
}
}
return $ret;
}
To see what this does, first try running it on a structure like this:
var $data = array (
0 => array('Name' => 'Kenny'),
1 => array('Name' => 'Lilo', 'Parent' => 0),
2 => array('Name' => 'Adrian', 'Parent' => 1)
3 => array('Name' => 'Mark', 'Parent' => 1)
);
var $tree = make_tree_structure($data, 'Parent');
If I’m not mistaken, you should get something like this out: (the “Parent” key would still be there, but I’m leaving it out for clarity)
array (
0 => array('Name' => 'Kenny', 'children' => array (
1 => array('Name' => 'Lilo', 'children' => array (
2 => array('Name' => 'Adrian')
3 => array('Name' => 'Mark')
)
)
)
Examine the code to see how it does this. Once you understand how this works, you can tweak it to work with your particular data.
Assuming you dont want any data/children tags in your array:
foreach ($this->db as $num => $category)
{
// save the data to the array
$this->tmp[$category->id] = array();
// save a reference to this item in the parent array
$this->tmp[$category->parent][$category->id] = &$this->tmp[$category->id];
$this->select_categories($category->id);
}
// the tree is at index $cat_id
return $this->tmp[$cat_id];
If you just need to retrieve the full tree out of the database, you can even simplify your query (get all records at once) and remove the recursive call in this function. You will need an extra check that will only set the $this->tmp[$catagory->id] when it does not exist and else it should merge the data with the existing data.

Replace keys in an array based on another lookup/mapping array

I have an associative array in the form key => value where key is a numerical value, however it is not a sequential numerical value. The key is actually an ID number and the value is a count. This is fine for most instances, however I want a function that gets the human-readable name of the array and uses that for the key, without changing the value.
I didn't see a function that does this, but I'm assuming I need to provide the old key and new key (both of which I have) and transform the array. Is there an efficient way of doing this?
$arr[$newkey] = $arr[$oldkey];
unset($arr[$oldkey]);
The way you would do this and preserve the ordering of the array is by putting the array keys into a separate array, find and replace the key in that array and then combine it back with the values.
Here is a function that does just that:
function change_key( $array, $old_key, $new_key ) {
if( ! array_key_exists( $old_key, $array ) )
return $array;
$keys = array_keys( $array );
$keys[ array_search( $old_key, $keys ) ] = $new_key;
return array_combine( $keys, $array );
}
if your array is built from a database query, you can change the key directly from the mysql statement:
instead of
"select ´id´ from ´tablename´..."
use something like:
"select ´id´ **as NEWNAME** from ´tablename´..."
The answer from KernelM is nice, but in order to avoid the issue raised by Greg in the comment (conflicting keys), using a new array would be safer
$newarr[$newkey] = $oldarr[$oldkey];
$oldarr=$newarr;
unset($newarr);
$array = [
'old1' => 1
'old2' => 2
];
$renameMap = [
'old1' => 'new1',
'old2' => 'new2'
];
$array = array_combine(array_map(function($el) use ($renameMap) {
return $renameMap[$el];
}, array_keys($array)), array_values($array));
/*
$array = [
'new1' => 1
'new2' => 2
];
*/
You could use a second associative array that maps human readable names to the id's. That would also provide a Many to 1 relationship. Then do something like this:
echo 'Widgets: ' . $data[$humanreadbleMapping['Widgets']];
If you want also the position of the new array key to be the same as the old one you can do this:
function change_array_key( $array, $old_key, $new_key) {
if(!is_array($array)){ print 'You must enter a array as a haystack!'; exit; }
if(!array_key_exists($old_key, $array)){
return $array;
}
$key_pos = array_search($old_key, array_keys($array));
$arr_before = array_slice($array, 0, $key_pos);
$arr_after = array_slice($array, $key_pos + 1);
$arr_renamed = array($new_key => $array[$old_key]);
return $arr_before + $arr_renamed + $arr_after;
}
Simple benchmark comparison of both solution.
Solution 1 Copy and remove (order lost, but way faster) https://stackoverflow.com/a/240676/1617857
<?php
$array = ['test' => 'value', ['etc...']];
$array['test2'] = $array['test'];
unset($array['test']);
Solution 2 Rename the key https://stackoverflow.com/a/21299719/1617857
<?php
$array = ['test' => 'value', ['etc...']];
$keys = array_keys( $array );
$keys[array_search('test', $keys, true)] = 'test2';
array_combine( $keys, $array );
Benchmark:
<?php
$array = ['test' => 'value', ['etc...']];
for ($i =0; $i < 100000000; $i++){
// Solution 1
}
for ($i =0; $i < 100000000; $i++){
// Solution 2
}
Results:
php solution1.php 6.33s user 0.02s system 99% cpu 6.356 total
php solution1.php 6.37s user 0.01s system 99% cpu 6.390 total
php solution2.php 12.14s user 0.01s system 99% cpu 12.164 total
php solution2.php 12.57s user 0.03s system 99% cpu 12.612 total
If your array is recursive you can use this function:
test this data:
$datos = array
(
'0' => array
(
'no' => 1,
'id_maquina' => 1,
'id_transaccion' => 1276316093,
'ultimo_cambio' => 'asdfsaf',
'fecha_ultimo_mantenimiento' => 1275804000,
'mecanico_ultimo_mantenimiento' =>'asdfas',
'fecha_ultima_reparacion' => 1275804000,
'mecanico_ultima_reparacion' => 'sadfasf',
'fecha_siguiente_mantenimiento' => 1275804000,
'fecha_ultima_falla' => 0,
'total_fallas' => 0,
),
'1' => array
(
'no' => 2,
'id_maquina' => 2,
'id_transaccion' => 1276494575,
'ultimo_cambio' => 'xx',
'fecha_ultimo_mantenimiento' => 1275372000,
'mecanico_ultimo_mantenimiento' => 'xx',
'fecha_ultima_reparacion' => 1275458400,
'mecanico_ultima_reparacion' => 'xx',
'fecha_siguiente_mantenimiento' => 1275372000,
'fecha_ultima_falla' => 0,
'total_fallas' => 0,
)
);
here is the function:
function changekeyname($array, $newkey, $oldkey)
{
foreach ($array as $key => $value)
{
if (is_array($value))
$array[$key] = changekeyname($value,$newkey,$oldkey);
else
{
$array[$newkey] = $array[$oldkey];
}
}
unset($array[$oldkey]);
return $array;
}
I like KernelM's solution, but I needed something that would handle potential key conflicts (where a new key may match an existing key). Here is what I came up with:
function swapKeys( &$arr, $origKey, $newKey, &$pendingKeys ) {
if( !isset( $arr[$newKey] ) ) {
$arr[$newKey] = $arr[$origKey];
unset( $arr[$origKey] );
if( isset( $pendingKeys[$origKey] ) ) {
// recursion to handle conflicting keys with conflicting keys
swapKeys( $arr, $pendingKeys[$origKey], $origKey, $pendingKeys );
unset( $pendingKeys[$origKey] );
}
} elseif( $newKey != $origKey ) {
$pendingKeys[$newKey] = $origKey;
}
}
You can then cycle through an array like this:
$myArray = array( '1970-01-01 00:00:01', '1970-01-01 00:01:00' );
$pendingKeys = array();
foreach( $myArray as $key => $myArrayValue ) {
// NOTE: strtotime( '1970-01-01 00:00:01' ) = 1 (a conflicting key)
$timestamp = strtotime( $myArrayValue );
swapKeys( $myArray, $key, $timestamp, $pendingKeys );
}
// RESULT: $myArray == array( 1=>'1970-01-01 00:00:01', 60=>'1970-01-01 00:01:00' )
Here is a helper function to achieve that:
/**
* Helper function to rename array keys.
*/
function _rename_arr_key($oldkey, $newkey, array &$arr) {
if (array_key_exists($oldkey, $arr)) {
$arr[$newkey] = $arr[$oldkey];
unset($arr[$oldkey]);
return TRUE;
} else {
return FALSE;
}
}
pretty based on #KernelM answer.
Usage:
_rename_arr_key('oldkey', 'newkey', $my_array);
It will return true on successful rename, otherwise false.
this code will help to change the oldkey to new one
$i = 0;
$keys_array=array("0"=>"one","1"=>"two");
$keys = array_keys($keys_array);
for($i=0;$i<count($keys);$i++) {
$keys_array[$keys_array[$i]]=$keys_array[$i];
unset($keys_array[$i]);
}
print_r($keys_array);
display like
$keys_array=array("one"=>"one","two"=>"two");
Easy stuff:
this function will accept the target $hash and $replacements is also a hash containing newkey=>oldkey associations.
This function will preserve original order, but could be problematic for very large (like above 10k records) arrays regarding performance & memory.
function keyRename(array $hash, array $replacements) {
$new=array();
foreach($hash as $k=>$v)
{
if($ok=array_search($k,$replacements))
$k=$ok;
$new[$k]=$v;
}
return $new;
}
this alternative function would do the same, with far better performance & memory usage, at the cost of losing original order (which should not be a problem since it is hashtable!)
function keyRename(array $hash, array $replacements) {
foreach($hash as $k=>$v)
if($ok=array_search($k,$replacements))
{
$hash[$ok]=$v;
unset($hash[$k]);
}
return $hash;
}
This page has been peppered with a wide interpretation of what is required because there is no minimal, verifiable example in the question body. Some answers are merely trying to solve the "title" without bothering to understand the question requirements.
The key is actually an ID number and the value is a count. This is
fine for most instances, however I want a function that gets the
human-readable name of the array and uses that for the key, without
changing the value.
PHP keys cannot be changed but they can be replaced -- this is why so many answers are advising the use of array_search() (a relatively poor performer) and unset().
Ultimately, you want to create a new array with names as keys relating to the original count. This is most efficiently done via a lookup array because searching for keys will always outperform searching for values.
Code: (Demo)
$idCounts = [
3 => 15,
7 => 12,
8 => 10,
9 => 4
];
$idNames = [
1 => 'Steve',
2 => 'Georgia',
3 => 'Elon',
4 => 'Fiona',
5 => 'Tim',
6 => 'Petra',
7 => 'Quentin',
8 => 'Raymond',
9 => 'Barb'
];
$result = [];
foreach ($idCounts as $id => $count) {
if (isset($idNames[$id])) {
$result[$idNames[$id]] = $count;
}
}
var_export($result);
Output:
array (
'Elon' => 15,
'Quentin' => 12,
'Raymond' => 10,
'Barb' => 4,
)
This technique maintains the original array order (in case the sorting matters), doesn't do any unnecessary iterating, and will be very swift because of isset().
If you want to replace several keys at once (preserving order):
/**
* Rename keys of an array
* #param array $array (asoc)
* #param array $replacement_keys (indexed)
* #return array
*/
function rename_keys($array, $replacement_keys) {
return array_combine($replacement_keys, array_values($array));
}
Usage:
$myarr = array("a" => 22, "b" => 144, "c" => 43);
$newkeys = array("x","y","z");
print_r(rename_keys($myarr, $newkeys));
//must return: array("x" => 22, "y" => 144, "z" => 43);
You can use this function based on array_walk:
function mapToIDs($array, $id_field_name = 'id')
{
$result = [];
array_walk($array,
function(&$value, $key) use (&$result, $id_field_name)
{
$result[$value[$id_field_name]] = $value;
}
);
return $result;
}
$arr = [0 => ['id' => 'one', 'fruit' => 'apple'], 1 => ['id' => 'two', 'fruit' => 'banana']];
print_r($arr);
print_r(mapToIDs($arr));
It gives:
Array(
[0] => Array(
[id] => one
[fruit] => apple
)
[1] => Array(
[id] => two
[fruit] => banana
)
)
Array(
[one] => Array(
[id] => one
[fruit] => apple
)
[two] => Array(
[id] => two
[fruit] => banana
)
)
This basic function handles swapping array keys and keeping the array in the original order...
public function keySwap(array $resource, array $keys)
{
$newResource = [];
foreach($resource as $k => $r){
if(array_key_exists($k,$keys)){
$newResource[$keys[$k]] = $r;
}else{
$newResource[$k] = $r;
}
}
return $newResource;
}
You could then loop through and swap all 'a' keys with 'z' for example...
$inputs = [
0 => ['a'=>'1','b'=>'2'],
1 => ['a'=>'3','b'=>'4']
]
$keySwap = ['a'=>'z'];
foreach($inputs as $k=>$i){
$inputs[$k] = $this->keySwap($i,$keySwap);
}
This function will rename an array key, keeping its position, by combining with index searching.
function renameArrKey($arr, $oldKey, $newKey){
if(!isset($arr[$oldKey])) return $arr; // Failsafe
$keys = array_keys($arr);
$keys[array_search($oldKey, $keys)] = $newKey;
$newArr = array_combine($keys, $arr);
return $newArr;
}
Usage:
$arr = renameArrKey($arr, 'old_key', 'new_key');
this works for renaming the first key:
$a = ['catine' => 'cat', 'canine' => 'dog'];
$tmpa['feline'] = $a['catine'];
unset($a['catine']);
$a = $tmpa + $a;
then, print_r($a) renders a repaired in-order array:
Array
(
[feline] => cat
[canine] => dog
)
this works for renaming an arbitrary key:
$a = ['canine' => 'dog', 'catine' => 'cat', 'porcine' => 'pig']
$af = array_flip($a)
$af['cat'] = 'feline';
$a = array_flip($af)
print_r($a)
Array
(
[canine] => dog
[feline] => cat
[porcine] => pig
)
a generalized function:
function renameKey($oldkey, $newkey, $array) {
$val = $array[$oldkey];
$tmp_A = array_flip($array);
$tmp_A[$val] = $newkey;
return array_flip($tmp_A);
}
There is an alternative way to change the key of an array element when working with a full array - without changing the order of the array.
It's simply to copy the array into a new array.
For instance, I was working with a mixed, multi-dimensional array that contained indexed and associative keys - and I wanted to replace the integer keys with their values, without breaking the order.
I did so by switching key/value for all numeric array entries - here: ['0'=>'foo']. Note that the order is intact.
<?php
$arr = [
'foo',
'bar'=>'alfa',
'baz'=>['a'=>'hello', 'b'=>'world'],
];
foreach($arr as $k=>$v) {
$kk = is_numeric($k) ? $v : $k;
$vv = is_numeric($k) ? null : $v;
$arr2[$kk] = $vv;
}
print_r($arr2);
Output:
Array (
[foo] =>
[bar] => alfa
[baz] => Array (
[a] => hello
[b] => world
)
)
best way is using reference, and not using unset (which make another step to clean memory)
$tab = ['two' => [] ];
solution:
$tab['newname'] = & $tab['two'];
you have one original and one reference with new name.
or if you don't want have two names in one value is good make another tab and foreach on reference
foreach($tab as $key=> & $value) {
if($key=='two') {
$newtab["newname"] = & $tab[$key];
} else {
$newtab[$key] = & $tab[$key];
}
}
Iterration is better on keys than clone all array, and cleaning old array if you have long data like 100 rows +++ etc..
One which preservers ordering that's simple to understand:
function rename_array_key(array $array, $old_key, $new_key) {
if (!array_key_exists($old_key, $array)) {
return $array;
}
$new_array = [];
foreach ($array as $key => $value) {
$new_key = $old_key === $key
? $new_key
: $key;
$new_array[$new_key] = $value;
}
return $new_array;
}
Here is an experiment (test)
Initial array (keys like 0,1,2)
$some_array[] = '6110';//
$some_array[] = '6111';//
$some_array[] = '6210';//
I must change key names to for example human_readable15, human_readable16, human_readable17
Something similar as already posted. During each loop i set necessary key name and remove corresponding key from the initial array.
For example, i inserted into mysql $some_array got lastInsertId and i need to send key-value pair back to jquery.
$first_id_of_inserted = 7;//lastInsertId
$last_loop_for_some_array = count($some_array);
for ($current_loop = 0; $current_loop < $last_loop_for_some_array ; $current_loop++) {
$some_array['human_readable'.($first_id_of_inserted + $current_loop)] = $some_array[$current_loop];//add new key for intial array
unset( $some_array[$current_loop] );//remove already renamed key from array
}
And here is the new array with renamed keys
echo '<pre>', print_r($some_array, true), '</pre>$some_array in '. basename(__FILE__, '.php'). '.php <br/>';
If instead of human_readable15, human_readable16, human_readable17 need something other. Then could create something like this
$arr_with_key_names[] = 'human_readable';
$arr_with_key_names[] = 'something_another';
$arr_with_key_names[] = 'and_something_else';
for ($current_loop = 0; $current_loop < $last_loop_for_some_array ; $current_loop++) {
$some_array[$arr_with_key_names[$current_loop]] = $some_array[$current_loop];//add new key for intial array
unset( $some_array[$current_loop] );//remove already renamed key from array
}
Hmm, I'm not test before, but I think this code working
function replace_array_key($data) {
$mapping = [
'old_key_1' => 'new_key_1',
'old_key_2' => 'new_key_2',
];
$data = json_encode($data);
foreach ($mapping as $needed => $replace) {
$data = str_replace('"'.$needed.'":', '"'.$replace.'":', $data);
}
return json_decode($data, true);
}
You can write simple function that applies the callback to the keys of the given array. Similar to array_map
<?php
function array_map_keys(callable $callback, array $array) {
return array_merge([], ...array_map(
function ($key, $value) use ($callback) { return [$callback($key) => $value]; },
array_keys($array),
$array
));
}
$array = ['a' => 1, 'b' => 'test', 'c' => ['x' => 1, 'y' => 2]];
$newArray = array_map_keys(function($key) { return 'new' . ucfirst($key); }, $array);
echo json_encode($array); // {"a":1,"b":"test","c":{"x":1,"y":2}}
echo json_encode($newArray); // {"newA":1,"newB":"test","newC":{"x":1,"y":2}}
Here is a gist https://gist.github.com/vardius/650367e15abfb58bcd72ca47eff096ca#file-array_map_keys-php.

Categories