Related
I have an array where I want to search the uid and get the key of the array.
Examples
Assume we have the following 2-dimensional array:
$userdb = array(
array(
'uid' => '100',
'name' => 'Sandra Shush',
'pic_square' => 'urlof100'
),
array(
'uid' => '5465',
'name' => 'Stefanie Mcmohn',
'pic_square' => 'urlof100'
),
array(
'uid' => '40489',
'name' => 'Michael',
'pic_square' => 'urlof40489'
)
);
The function call search_by_uid(100) (uid of first user) should return 0.
The function call search_by_uid(40489) should return 2.
I tried making loops, but I want a faster executing code.
function searchForId($id, $array) {
foreach ($array as $key => $val) {
if ($val['uid'] === $id) {
return $key;
}
}
return null;
}
This will work. You should call it like this:
$id = searchForId('100', $userdb);
It is important to know that if you are using === operator compared types have to be exactly same, in this example you have to search string or just use == instead ===.
Based on angoru answer. In later versions of PHP (>= 5.5.0) you can use one-liner.
$key = array_search('100', array_column($userdb, 'uid'));
Here is documentation: http://php.net/manual/en/function.array-column.php.
If you are using (PHP 5 >= 5.5.0) you don't have to write your own function to do this, just write this line and it's done.
If you want just one result:
$key = array_search(40489, array_column($userdb, 'uid'));
For multiple results
$keys = array_keys(array_column($userdb, 'uid'), 40489);
In case you have an associative array as pointed in the comments you could make it with:
$keys = array_keys(array_combine(array_keys($userdb), array_column($userdb, 'uid')),40489);
If you are using PHP < 5.5.0, you can use this backport, thanks ramsey!
Update: I've been making some simple benchmarks and the multiple results form seems to be the fastest one, even faster than the Jakub custom function!
In later versions of PHP (>= 5.5.0) you can use this one-liner:
$key = array_search('100', array_column($userdb, 'uid'));
Building off Jakub's excellent answer, here is a more generalized search that will allow the key to specified (not just for uid):
function searcharray($value, $key, $array) {
foreach ($array as $k => $val) {
if ($val[$key] == $value) {
return $k;
}
}
return null;
}
Usage: $results = searcharray('searchvalue', searchkey, $array);
Looks array_filter will be suitable solution for this...
$userdb=Array
(
(0) => Array
(
(uid) => '100',
(name) => 'Sandra Shush',
(url) => 'urlof100'
),
(1) => Array
(
(uid) => '5465',
(name) => 'Stefanie Mcmohn',
(pic_square) => 'urlof100'
),
(2) => Array
(
(uid) => '40489',
(name) => 'Michael',
(pic_square) => 'urlof40489'
)
);
PHP Code
<?php
$search = 5465;
$found = array_filter($userdb,function($v,$k) use ($search){
return $v['uid'] == $search;
},ARRAY_FILTER_USE_BOTH); // With latest PHP third parameter is optional.. Available Values:- ARRAY_FILTER_USE_BOTH OR ARRAY_FILTER_USE_KEY
$values= print_r(array_values($found));
$keys = print_r(array_keys($found));
I know this was already answered, but I used this and extended it a little more in my code so that you didn't have search by only the uid. I just want to share it for anyone else who may need that functionality.
Here's my example and please bare in mind this is my first answer. I took out the param array because I only needed to search one specific array, but you could easily add it in. I wanted to essentially search by more than just the uid.
Also, in my situation there may be multiple keys to return as a result of searching by other fields that may not be unique.
/**
* #param array multidimensional
* #param string value to search for, ie a specific field name like name_first
* #param string associative key to find it in, ie field_name
*
* #return array keys.
*/
function search_revisions($dataArray, $search_value, $key_to_search) {
// This function will search the revisions for a certain value
// related to the associative key you are looking for.
$keys = array();
foreach ($dataArray as $key => $cur_value) {
if ($cur_value[$key_to_search] == $search_value) {
$keys[] = $key;
}
}
return $keys;
}
Later, I ended up writing this to allow me to search for another value and associative key. So my first example allows you to search for a value in any specific associative key, and return all the matches.
This second example shows you where a value ('Taylor') is found in a certain associative key (first_name) AND another value (true) is found in another associative key (employed), and returns all matches (Keys where people with first name 'Taylor' AND are employed).
/**
* #param array multidimensional
* #param string $search_value The value to search for, ie a specific 'Taylor'
* #param string $key_to_search The associative key to find it in, ie first_name
* #param string $other_matching_key The associative key to find in the matches for employed
* #param string $other_matching_value The value to find in that matching associative key, ie true
*
* #return array keys, ie all the people with the first name 'Taylor' that are employed.
*/
function search_revisions($dataArray, $search_value, $key_to_search, $other_matching_value = null, $other_matching_key = null) {
// This function will search the revisions for a certain value
// related to the associative key you are looking for.
$keys = array();
foreach ($dataArray as $key => $cur_value) {
if ($cur_value[$key_to_search] == $search_value) {
if (isset($other_matching_key) && isset($other_matching_value)) {
if ($cur_value[$other_matching_key] == $other_matching_value) {
$keys[] = $key;
}
} else {
// I must keep in mind that some searches may have multiple
// matches and others would not, so leave it open with no continues.
$keys[] = $key;
}
}
}
return $keys;
}
Use of function
$data = array(
array(
'cust_group' => 6,
'price' => 13.21,
'price_qty' => 5
),
array(
'cust_group' => 8,
'price' => 15.25,
'price_qty' => 4
),
array(
'cust_group' => 8,
'price' => 12.75,
'price_qty' => 10
)
);
$findKey = search_revisions($data,'8', 'cust_group', '10', 'price_qty');
print_r($findKey);
Result
Array ( [0] => 2 )
You can do that with combination of two functions, array_search & array_column.
$search_value = '5465';
$search_key = 'uid';
$user = array_search($search_value, array_column($userdb, $search_key));
print_r($userdb[$user]);
5465 is the user ID you want to search, uid is the key that contains user ID and $userdb is the array that is defined in the question.
References:
array_search on php.net
array_column on php.net
I modified one of examples below description function array_search. Function searchItemsByKey return all value(s) by $key from multidimensional array ( N levels). Perhaps , it would be useful for somebody. Example:
$arr = array(
'XXX'=>array(
'YYY'=> array(
'AAA'=> array(
'keyN' =>'value1'
)
),
'ZZZ'=> array(
'BBB'=> array(
'keyN' => 'value2'
)
)
//.....
)
);
$result = searchItemsByKey($arr,'keyN');
print '<pre>';
print_r($result);
print '<pre>';
// OUTPUT
Array
(
[0] => value1
[1] => value2
)
Function code:
function searchItemsByKey($array, $key)
{
$results = array();
if (is_array($array))
{
if (isset($array[$key]) && key($array)==$key)
$results[] = $array[$key];
foreach ($array as $sub_array)
$results = array_merge($results, searchItemsByKey($sub_array, $key));
}
return $results;
}
Here is one liner for the same,
$pic_square = $userdb[array_search($uid,array_column($userdb, 'uid'))]['pic_square'];
Even though this is an old question and has an accepted answer, Thought i would suggest one change to the accepted answer.. So first off, i agree the accepted answer is correct here.
function searchArrayKeyVal($sKey, $id, $array) {
foreach ($array as $key => $val) {
if ($val[$sKey] == $id) {
return $key;
}
}
return false;
}
Replacing the preset 'uid' with a parameter in the function instead, so now calling the below code means you can use the one function across multiple array types. Small change, but one that makes the slight difference.
// Array Data Of Users
$userdb = array (
array ('uid' => '100','name' => 'Sandra Shush','url' => 'urlof100' ),
array ('uid' => '5465','name' => 'Stefanie Mcmohn','url' => 'urlof100' ),
array ('uid' => '40489','name' => 'Michael','url' => 'urlof40489' ),
);
// Obtain The Key Of The Array
$arrayKey = searchArrayKeyVal("uid", '100', $userdb);
if ($arrayKey!==false) {
echo "Search Result: ", $userdb[$arrayKey]['name'];
} else {
echo "Search Result can not be found";
}
PHP Fiddle Example
I want to check tha in the following array $arr is there 'abc' exists in sub arrays or not
$arr = array(
array(
'title' => 'abc'
)
);
Then i can use this
$res = array_search('abc', array_column($arr, 'title'));
if($res == ''){
echo 'exists';
} else {
echo 'notExists';
}
I think This is the Most simple way to define
I had to use un function which finds every elements in an array. So I modified the function done by Jakub Truneček as follow:
function search_in_array_r($needle, $array) {
$found = array();
foreach ($array as $key => $val) {
if ($val[1] == $needle) {
array_push($found, $val[1]);
}
}
if (count($found) != 0)
return $found;
else
return null;
}
/**
* searches a simple as well as multi dimension array
* #param type $needle
* #param type $haystack
* #return boolean
*/
public static function in_array_multi($needle, $haystack){
$needle = trim($needle);
if(!is_array($haystack))
return False;
foreach($haystack as $key=>$value){
if(is_array($value)){
if(self::in_array_multi($needle, $value))
return True;
else
self::in_array_multi($needle, $value);
}
else
if(trim($value) === trim($needle)){//visibility fix//
error_log("$value === $needle setting visibility to 1 hidden");
return True;
}
}
return False;
}
you can use this function ;
https://github.com/serhatozles/ArrayAdvancedSearch
<?php
include('ArraySearch.php');
$query = "a='Example World' and b>='2'";
$Array = array(
'a' => array('d' => '2'),
array('a' => 'Example World','b' => '2'),
array('c' => '3'), array('d' => '4'),
);
$Result = ArraySearch($Array,$query,1);
echo '<pre>';
print_r($Result);
echo '</pre>';
// Output:
// Array
// (
// [0] => Array
// (
// [a] => Example World
// [b] => 2
// )
//
// )
$a = ['x' => ['eee', 'ccc'], 'b' => ['zzz']];
$found = null;
$search = 'eee';
array_walk($a, function ($k, $v) use ($search, &$found) {
if (in_array($search, $k)) {
$found = $v;
}
});
var_dump($found);
Try this
<?php
function recursive_array_search($needle,$haystack) {
foreach($haystack as $key=>$value) {
$current_key=$key;
if($needle===$value OR (is_array($value) &&
recursive_array_search($needle,$value) !== false)) {
return $current_key;
}
}
return false;
}
?>
Just share, maybe can like this.
if( ! function_exists('arraySearchMulti')){
function arraySearchMulti($search,$key,$array,$returnKey=false)
{
foreach ($array as $k => $val) {
if (isset($val[$key])) {
if ((string)$val[$key] == (string)$search) {
return ($returnKey ? $k : $val);
}
}else{
return (is_array($val) ? arraySearchMulti($search,$key,$val,$returnKey) : null);
}
}
return null;
}}
No one else has used array_reduce yet, so thought I'd add this approach...
$find_by_uid = '100';
$is_in_array = array_reduce($userdb, function($carry, $user) use ($find_by_uid){
return $carry ? $carry : $user['uid'] === $find_by_uid;
});
// Returns true
Gives you more fine control over the 'search' logic than array_search().
Note that I have used strict equality here but you could opt for different comparison logic. The $carry means the comparison needs to be true once, and the final result will be TRUE.
I was looking for functionality similar to that of MySQL LIKE %term%. Based on the answers on this page. I am able to search the JSON array from a file.
user_list.json looks as sample below:
{
"user-23456": {
"name": "John Doe",
"age": "20",
"email": "doe#sample.com",
"user_id": "23456"
},
"user-09876": {
"name": "Ronojoy Adams",
"age": "35",
"email": "joy#sample.com",
"user_id": "09876"
},
"user-34890": {
"name": "Will Artkin",
"age": "16",
"email": "will#sample.com",
"user_id": "34890"
},
}
/*
*search_key_like
*/
function search_key_like($value, $key, $array) {
$results=array();
$keyword = preg_quote($value, '~');
foreach ($array as $k => $val) {
//if name a is spell John and keyword is sent as joh or JOH it will return null
//to fix the issue convert the string into lowercase and uppercase
$data=array($val[$key],strtolower($val[$key]),strtoupper($val[$key]));
if (preg_grep('~' . $keyword . '~', $data)) {
array_push($results,$val[$key]);
}
}
return $results;
}
Usage===pulling the JSON file===
$user_list_json='./user_list.json';
if(file_exists($user_list_json) && file_get_contents($user_list_json)){
$file_json_data=file_get_contents($user_list_json);
$json_array_data=json_decode($file_json_data,true);
$user_name_like = search_key_like('ron', 'name', $json_array_data);
print "<pre>".print_r($user_name_like,true);
}
for( $i =0; $i < sizeof($allUsers); $i++)
{
$NEEDLE1='firstname';
$NEEDLE2='emailAddress';
$sterm='Tofind';
if(isset($allUsers[$i][$NEEDLE1]) && isset($allUsers[$i][$NEEDLE2])
{
$Fname= $allUsers[$i][$NEEDLE1];
$Lname= $allUsers[$i][$NEEDLE2];
$pos1 = stripos($Fname, $sterm);
$pos2=stripos($Lname, $sterm);//not case sensitive
if($pos1 !== false ||$pos2 !== false)
{$resultsMatched[] =$allUsers[$i];}
else
{ continue;}
}
}
Print_r($resultsMatched); //will give array for matched values even partially matched
With help of above code one can find any(partially matched) data from any column in 2D array so user id can be found as required in question.
Expanding on the function #mayhem created, this example would be more of a "fuzzy" search in case you just want to match part (most) of a search string:
function searchArrayKeyVal($sKey, $id, $array) {
foreach ($array as $key => $val) {
if (strpos(strtolower($val[$sKey]), strtolower(trim($id))) !== false) {
return $key;
}
}
return false;
}
For example the value in the array is Welcome to New York! and you wanted the first instance of just "New York!"
If question i.e.
$a = [
[
"_id" => "5a96933414d48831a41901f2",
"discount_amount" => 3.29,
"discount_id" => "5a92656a14d488570c2c44a2",
],
[
"_id" => "5a9790fd14d48879cf16a9e8",
"discount_amount" => 4.53,
"discount_id" => "5a9265b914d488548513b122",
],
[
"_id" => "5a98083614d488191304b6c3",
"discount_amount" => 15.24,
"discount_id" => "5a92806a14d48858ff5c2ec3",
],
[
"_id" => "5a982a4914d48824721eafe3",
"discount_amount" => 45.74,
"discount_id" => "5a928ce414d488609e73b443",
],
[
"_id" => "5a982a4914d48824721eafe55",
"discount_amount" => 10.26,
"discount_id" => "5a928ce414d488609e73b443",
],
];
Ans:
function searchForId($id, $array) {
$did=0;
$dia=0;
foreach ($array as $key => $val) {
if ($val['discount_id'] === $id) {
$dia +=$val['discount_amount'];
$did++;
}
}
if($dia != '') {
echo $dia;
var_dump($did);
}
return null;
};
print_r(searchForId('5a928ce414d488609e73b443',$a));
Here is a better solution, in case your pulling data from a database or a multidimensional array
Example of a multidimensional array:
$records = array(
array(
'id' => 2135,
'first_name' => 'John',
'last_name' => 'Doe',
),
array(
'id' => 3245,
'first_name' => 'Sally',
'last_name' => 'Smith',
),
array(
'id' => 5342,
'first_name' => 'Jane',
'last_name' => 'Jones',
),
array(
'id' => 5623,
'first_name' => 'Peter',
'last_name' => 'Doe',
)
);
function search_user_by_name($name, $array) {
foreach ($array as $keys) {
foreach ($keys as $key => $_user_record) {
if ($_user_record == $name) {
return [$key => $_user_record];//Return and array of user
}
}
}
return null;
}
Call the function:
$results = search_user_by_name('John', $records);
print_r($results);
Output: Array ( [first_name] => John )
I have an array like the below:
$arrays = [
'a' => [
'name' => "Name 1",
'age' => "99",
'add' => ""
],
'b' => [
'name' => "Name 2",
'age' => "99",
'add' => "Add2"
],
'c' => [
'name' => "Name 3",
'age' => "99",
'add' => "Add3"
],
'd' => [
'name' => "",
'age' => "",
'add' => "Add4"
]
];
I want to get a result like:
$res = [
'a' => ['add'],
'd' => ['name','age']
];
I have tried with the below code, but it returns 1.
$status = array_walk_recursive($arrays, function($v, $k) {
global $output;
if (empty($v) && $v !== 0)
$output[$k] = $v;
});
I want to do it without using any loops because my real input array is very large and I am concerned with performance.
If your input is always of a fixed depth, you can map the existing values to the keys of all empty items:
$output = array_map(function($row) {
return array_keys(array_filter($row, function ($e) {
return empty($e) && $e !== 0;
}));
}, $arrays);
The outer function runs for each "row", the value of which is then converted into a list of all keys with empty values (excluding zeroes, as in the question).
This will keep the outer keys B & C as empty arrays, so if you want them to be removed as well then run another iteration of array_filter over the result:
$output = array_filter($output)
See https://3v4l.org/c23ZB
As mentioned in the comments, there are still several loops going on here, they're just not as visible in the code. A regular foreach loop might end up being a lot easier to read, and possibly perform faster as well.
You can use next combination of array_walk & array_filter:
$result = [];
array_walk(
$arrays,
function($el, $key) use(&$result) {
$empty = array_filter($el, function($el){return $el == "";});
$empty_keys = array_keys($empty);
if (count($empty_keys)) $result[$key] = $empty_keys;
}
);
Try it here
This is another way to achieve your desired output.
$result = [];
foreach($arrays as $key => $value) {
$empty_arr = array_filter($value, function ($ele) {
return empty($ele);
});
$empty_arr_keys = array_keys($empty_arr);
if(!empty($empty_arr_keys)) $result[$key] = $empty_arr_keys;
}
print_r($result);
#iainn's answer can be sharpened up by calling !strlen() on the deep values.
Code: (Demo)
var_export(
array_filter(
array_map(
fn($row) => array_keys(
array_filter(
$row,
fn($v) => !strlen($v)
)
),
$array
)
)
);
But you will end up making fewer iterations and writing cleaner, more intuitive/readable code if you use classic loops. This is how I would write it in my own project:
Code: (Demo)
$result = [];
foreach ($array as $rowKey => $row) {
foreach ($row as $key => $value) {
if (!strlen($value)) {
$result[$rowKey][] = $key;
}
}
}
var_export($result);
This question already has answers here:
PHP rename array keys in multidimensional array
(10 answers)
Closed last month.
When I var_dump on a variable called $tags (a multidimensional array) I get this:
Array
(
[0] => Array
(
[name] => tabbing
[url] => tabbing
)
[1] => Array
(
[name] => tabby ridiman
[url] => tabby-ridiman
)
[2] => Array
(
[name] => tables
[url] => tables
)
[3] => Array
(
[name] => tabloids
[url] => tabloids
)
[4] => Array
(
[name] => taco bell
[url] => taco-bell
)
[5] => Array
(
[name] => tacos
[url] => tacos
)
)
I would like to rename all array keys called "url" to be called "value". What would be a good way to do this?
You could use array_map() to do it.
$tags = array_map(function($tag) {
return array(
'name' => $tag['name'],
'value' => $tag['url']
);
}, $tags);
Loop through, set new key, unset old key.
foreach($tags as &$val){
$val['value'] = $val['url'];
unset($val['url']);
}
Talking about functional PHP, I have this more generic answer:
array_map(function($arr){
$ret = $arr;
$ret['value'] = $ret['url'];
unset($ret['url']);
return $ret;
}, $tag);
}
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;
}
foreach ($basearr as &$row)
{
$row['value'] = $row['url'];
unset( $row['url'] );
}
unset($row);
This should work in most versions of PHP 4+. Array map using anonymous functions is not supported below 5.3.
Also the foreach examples will throw a warning when using strict PHP error handling.
Here is a small multi-dimensional key renaming function. It can also be used to process arrays to have the correct keys for integrity throughout your app. It will not throw any errors when a key does not exist.
function multi_rename_key(&$array, $old_keys, $new_keys)
{
if(!is_array($array)){
($array=="") ? $array=array() : false;
return $array;
}
foreach($array as &$arr){
if (is_array($old_keys))
{
foreach($new_keys as $k => $new_key)
{
(isset($old_keys[$k])) ? true : $old_keys[$k]=NULL;
$arr[$new_key] = (isset($arr[$old_keys[$k]]) ? $arr[$old_keys[$k]] : null);
unset($arr[$old_keys[$k]]);
}
}else{
$arr[$new_keys] = (isset($arr[$old_keys]) ? $arr[$old_keys] : null);
unset($arr[$old_keys]);
}
}
return $array;
}
Usage is simple. You can either change a single key like in your example:
multi_rename_key($tags, "url", "value");
or a more complex multikey
multi_rename_key($tags, array("url","name"), array("value","title"));
It uses similar syntax as preg_replace() where the amount of $old_keys and $new_keys should be the same. However when they are not a blank key is added. This means you can use it to add a sort if schema to your array.
Use this all the time, hope it helps!
Very simple approach to replace keys in a multidimensional array, and maybe even a bit dangerous, but should work fine if you have some kind of control over the source array:
$array = [ 'oldkey' => [ 'oldkey' => 'wow'] ];
$new_array = json_decode(str_replace('"oldkey":', '"newkey":', json_encode($array)));
print_r($new_array); // [ 'newkey' => [ 'newkey' => 'wow'] ]
This doesn't have to be difficult in the least. You can simply assign the arrays around regardless of how deep they are in a multi-dimensional array:
$array['key_old'] = $array['key_new'];
unset($array['key_old']);
You can do it without any loop
Like below
$tags = str_replace("url", "value", json_encode($tags));
$tags = json_decode($tags, true);
class DataHelper{
private static function __renameArrayKeysRecursive($map = [], &$array = [], $level = 0, &$storage = []) {
foreach ($map as $old => $new) {
$old = preg_replace('/([\.]{1}+)$/', '', trim($old));
if ($new) {
if (!is_array($new)) {
$array[$new] = $array[$old];
$storage[$level][$old] = $new;
unset($array[$old]);
} else {
if (isset($array[$old])) {
static::__renameArrayKeysRecursive($new, $array[$old], $level + 1, $storage);
} else if (isset($array[$storage[$level][$old]])) {
static::__renameArrayKeysRecursive($new, $array[$storage[$level][$old]], $level + 1, $storage);
}
}
}
}
}
/**
* Renames array keys. (add "." at the end of key in mapping array if you want rename multidimentional array key).
* #param type $map
* #param type $array
*/
public static function renameArrayKeys($map = [], &$array = [])
{
$storage = [];
static::__renameArrayKeysRecursive($map, $array, 0, $storage);
unset($storage);
}
}
Use:
DataHelper::renameArrayKeys([
'a' => 'b',
'abc.' => [
'abcd' => 'dcba'
]
], $yourArray);
It is from duplicated question
$json = '[
{"product_id":"63","product_batch":"BAtch1","product_quantity":"50","product_price":"200","discount":"0","net_price":"20000"},
{"product_id":"67","product_batch":"Batch2","product_quantity":"50","product_price":"200","discount":"0","net_price":"20000"}
]';
$array = json_decode($json, true);
$out = array_map(function ($product) {
return array_merge([
'price' => $product['product_price'],
'quantity' => $product['product_quantity'],
], array_flip(array_filter(array_flip($product), function ($value) {
return $value != 'product_price' && $value != 'product_quantity';
})));
}, $array);
var_dump($out);
https://repl.it/#Piterden/Replace-keys-in-array
This is how I rename keys, especially with data that has been uploaded in a spreadsheet:
function changeKeys($array, $new_keys) {
$newArray = [];
foreach($array as $row) {
$oldKeys = array_keys($row);
$indexedRow = [];
foreach($new_keys as $index => $newKey)
$indexedRow[$newKey] = isset($oldKeys[$index]) ? $row[$oldKeys[$index]] : '';
$newArray[] = $indexedRow;
}
return $newArray;
}
Based on the great solution provided by Alex, I created a little more flexible solution based on a scenario I was dealing with. So now you can use the same function for multiple arrays with different numbers of nested key pairs, you just need to pass in an array of key names to use as replacements.
$data_arr = [
0 => ['46894', 'SS'],
1 => ['46855', 'AZ'],
];
function renameKeys(&$data_arr, $columnNames) {
// change key names to be easier to work with.
$data_arr = array_map(function($tag) use( $columnNames) {
$tempArray = [];
$foreachindex = 0;
foreach ($tag as $key => $item) {
$tempArray[$columnNames[$foreachindex]] = $item;
$foreachindex++;
}
return $tempArray;
}, $data_arr);
}
renameKeys($data_arr, ["STRATEGY_ID","DATA_SOURCE"]);
this work perfectly for me
$some_options = array();;
if( !empty( $some_options ) ) {
foreach( $some_options as $theme_options_key => $theme_options_value ) {
if (strpos( $theme_options_key,'abc') !== false) { //first we check if the value contain
$theme_options_new_key = str_replace( 'abc', 'xyz', $theme_options_key ); //if yes, we simply replace
unset( $some_options[$theme_options_key] );
$some_options[$theme_options_new_key] = $theme_options_value;
}
}
}
return $some_options;
Is there a way to change all the numeric keys to "Name" without looping through the array (so a php function)?
[
0 => 'blabla',
1 => 'blabla',
2 => 'blblll',
// etc ...
]
If you have an array of keys that you want to use then use array_combine
Given $keys = array('a', 'b', 'c', ...) and your array, $list, then do this:
$list = array_combine($keys, array_values($list));
List will now be array('a' => 'blabla 1', ...) etc.
You have to use array_values to extract just the values from the array and not the old, numeric, keys.
That's nice and simple looking but array_values makes an entire copy of the array so you could have space issues. All we're doing here is letting php do the looping for us, not eliminate the loop. I'd be tempted to do something more like:
foreach ($list as $k => $v) {
unset ($list[$k]);
$new_key = *some logic here*
$list[$new_key] = $v;
}
I don't think it's all that more efficient than the first code but it provides more control and won't have issues with the length of the arrays.
No, there is not, for starters, it is impossible to have an array with elements sharing the same key
$x =array();
$x['foo'] = 'bar' ;
$x['foo'] = 'baz' ; #replaces 'bar'
Secondarily, if you wish to merely prefix the numbers so that
$x[0] --> $x['foo_0']
That is computationally implausible to do without looping. No php functions presently exist for the task of "key-prefixing", and the closest thing is "extract" which will prefix numeric keys prior to making them variables.
The very simplest way is this:
function rekey( $input , $prefix ) {
$out = array();
foreach( $input as $i => $v ) {
if ( is_numeric( $i ) ) {
$out[$prefix . $i] = $v;
continue;
}
$out[$i] = $v;
}
return $out;
}
Additionally, upon reading XMLWriter usage, I believe you would be writing XML in a bad way.
<section>
<foo_0></foo_0>
<foo_1></foo_1>
<bar></bar>
<foo_2></foo_2>
</section>
Is not good XML.
<section>
<foo></foo>
<foo></foo>
<bar></bar>
<foo></foo>
</section>
Is better XML, because when intrepreted, the names being duplicate don't matter because they're all offset numerically like so:
section => {
0 => [ foo , {} ]
1 => [ foo , {} ]
2 => [ bar , {} ]
3 => [ foo , {} ]
}
This is an example prefixing all the keys with an underscore.
We use array_combine to combine the array keys with the array values, but we first run an array_map function on the array keys, which takes a simple function that adds the prefix.
$prefix = '_';
$arr = array_combine(
array_map(function($v) use ($prefix){
return $prefix.$v;
}, array_keys($arr)),
array_values($arr)
);
See a live example here https://3v4l.org/HABl7
I added this for an answer to another question and seemed relevant. Hopefully might help someone that needs to change the value of the keys in an array. Uses built-in functions for php.
$inputArray = array('app_test' => 'test', 'app_two' => 'two');
/**
* Used to remap keys of an array by removing the prefix passed in
*
* Example:
* $inputArray = array('app_test' => 'test', 'app_two' => 'two');
* $keys = array_keys($inputArray);
* array_walk($keys, 'removePrefix', 'app_');
* $remappedArray = array_combine($keys, $inputArray);
*
* #param $value - key value to replace, should be from array_keys
* #param $omit - unused, needed for prefix call
* #param $prefix - prefix to string replace in keys
*/
function removePrefix(&$value, $omit, $prefix) {
$value = str_replace($prefix, '', $value);
}
// first get all the keys to remap
$keys = array_keys($inputArray);
// perform internal iteration with prefix passed into walk function for dynamic replace of key
array_walk($keys, 'removePrefix', 'app_');
// combine the rewritten keys and overwrite the originals
$remappedArray = array_combine($keys, $inputArray);
// see full output of comparison
var_dump($inputArray);
var_dump($remappedArray);
Output:
array(2) {
'attr_test' =>
string(4) "test"
'attr_two' =>
string(3) "two"
}
array(2) {
'test' =>
string(4) "test"
'two' =>
string(3) "two"
}
I think that he want:
$a = array(1=>'first_name', 2=>'last_name');
$a = array_flip($a);
$a['first_name'] = 3;
$a = array_flip($a);
print_r($a);
The solution to when you're using XMLWriter (native to PHP 5.2.x<) is using $xml->startElement('itemName'); this will replace the arrays key.
change array key name "group" to "children".
<?php
echo json_encode($data);
function array_change_key_name( $orig, $new, &$array ) {
foreach ( $array as $k => $v ) {
$res[ $k === $orig ? $new : $k ] = ( (is_array($v)||is_object($v)) ? array_change_key_name( $orig, $new, $v ) : $v );
}
return $res;
}
echo '<br>=====change "group" to "children"=====<br>';
$new = array_change_key_name("group" ,"children" , $data);
echo json_encode($new);
?>
result:
{"benchmark":[{"idText":"USGCB-Windows-7","title":"USGCB: Guidance for Securing Microsoft Windows 7 Systems for IT Professional","profile":[{"idText":"united_states_government_configuration_baseline_version_1.2.0.0","title":"United States Government Configuration Baseline 1.2.0.0","group":[{"idText":"security_components_overview","title":"Windows 7 Security Components Overview","group":[{"idText":"new_features","title":"New Features in Windows 7"}]},{"idText":"usgcb_security_settings","title":"USGCB Security Settings","group":[{"idText":"account_policies_group","title":"Account Policies group"}]}]}]}]}
=====change "group" to "children"=====
{"benchmark":[{"idText":"USGCB-Windows-7","title":"USGCB: Guidance for Securing Microsoft Windows 7 Systems for IT Professional","profile":[{"idText":"united_states_government_configuration_baseline_version_1.2.0.0","title":"United States Government Configuration Baseline 1.2.0.0","children":[{"idText":"security_components_overview","title":"Windows 7 Security Components Overview","children":[{"idText":"new_features","title":"New Features in Windows 7"}]},{"idText":"usgcb_security_settings","title":"USGCB Security Settings","children":[{"idText":"account_policies_group","title":"Account Policies group"}]}]}]}]}
Use array array_flip in php
$array = array ( [1] => Sell [2] => Buy [3] => Rent [4] => Jobs )
print_r(array_flip($array));
Array ( [Sell] => 1 [Buy] => 2 [Rent] => 3 [Jobs] => 4 )
I did this for an array of objects. Its basically creating new keys in the same array and unsetting the old keys.
public function transform($key, $results)
{
foreach($results as $k=>$result)
{
if( property_exists($result, $key) )
{
$results[$result->$key] = $result;
unset($results[$k]);
}
}
return $results;
}
<?php
$array[$new_key] = $array[$old_key];
unset($array[$old_key]);
?>
To have the same key I think they must be in separate nested arrays.
for ($i = 0; $i < count($array); $i++) {
$newArray[] = ['name' => $array[$i]];
};
Output:
0 => array:1 ["name" => "blabla"]
1 => array:1 ["name" => "blabla"]
2 => array:1 ["name" => "blblll"]
You could create a new array containing that array, so:
<?php
$array = array();
$array['name'] = $oldArray;
?>
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.