Assume I have the following array:
$array(
'32' => array('name' => 'paul', 'age' => 43),
'17' => array('name' => 'eric', 'age' => 19),
'99' => array('name' => 'dave', 'age' => 65)
)
I am only interested in the first $array item:
$array2 = array('key'=> 32, 'name' => 'paul', 'age' => 43)
What is the most efficient way to accomplish this? In other words, can I throw out all other items of $array with one command?
Use array_shift().
array_shift() shifts the first value of the array off and returns it,
shortening the array by one element and moving everything down. All
numerical array keys will be modified to start counting from zero
while literal keys won't be touched.
$array2 = array_shift($array);
This means that $array2 now holds the first element, while $array holds the rest of the elements.
try this
$array2 = array_shift($array);
$newArr = reset($array);
I think there is no problem with that.
There are 2 options, really. Either you can just select the first item in the array
$array2 = $array[0];
Or you could use array_slice as
$array2 = array_slice($array, 0, 1);
Array_shift is probably the best way. But just for fun here is another way.
$first_element = end(array_reverse($array));
$k = array_merge(array('key' => key($array)), array_shift($array));
Returns in the specified format.
key gets you the first key, array_shift gets you the first value, and merge using array_merge
resetting an array also returns the first element (end() returns the last):
$first = reset( $array );
http://www.php.net/manual/en/function.reset.php
But to generate the exact result you want, you could write something like this
foreach( $array as $k => $first ){ // get first sub-array and its key
$first['key'] = $k; // add the key
break; // we don't care about the other elements, goodbye
}
Futuregeek's method fixed:
$first =
// returns first element, and sets it as the current element for key()
reset( $array )
// instead of array_merge, (sometimes) you can use the + operator
+
// key() will return the appropriate key after reset()
array('key' => key( $array ));
Try It :
$arr = array(
'32' => array('name' => 'paul', 'age' => 43),
'17' => array('name' => 'eric', 'age' => 19),
'99' => array('name' => 'dave', 'age' => 65)
);
foreach($arr as $key => $value)
{
$result[$key] = $value;
break;
}
print_r($result);
##-------Secount Way If you don't want Key 32--------------------------
$arr = array(
'32' => array('name' => 'paul', 'age' => 43),
'17' => array('name' => 'eric', 'age' => 19),
'99' => array('name' => 'dave', 'age' => 65)
);
$arr = array_reverse($arr);
print_r(end($arr));
#------ Third Way If you don't want Key 32 -------------
echo "<br>=======<br>";
$arr = array(
'32' => array('name' => 'paul', 'age' => 43),
'17' => array('name' => 'eric', 'age' => 19),
'99' => array('name' => 'dave', 'age' => 65)
);
$array2 = array_shift($arr);
print_r($array2);
Related
I have array like this :
$a = array('value' =>
array(
'lesson_id' => array('1','6'),
'knowledge_value' => array('2','7'),
'knowledge_description' => array('3','8'),
'skill_value' => array('4','9'),
'skill_description' => array('5','10')
)
);
I want to change it to be like this :
$a = array('value' =>
array(
array(
'lesson_id' => '1',
'knowledge_value' => '2',
'knowledge_description' => '3',
'skill_value' => '4',
'skill_description' => '5'
),
array(
'lesson_id' => '6',
'knowledge_value' => '7',
'knowledge_description' => '8',
'skill_value' => '9',
'skill_description' => '10'
),
)
);
How can I do it?
Demo Link
Here is the snippet for you to work, please see inline doc for explanation
$temp = [];
$keys = array_keys($a['value']); // fetched all keys
for ($i = 0; $i < count($a['value']['lesson_id']); $i++) { // compared with first count of lession_id
$temp['value'][] = array_combine($keys, array_column($a['value'], $i)); // combined key and values
}
array_keys ā Return all the keys or a subset of the keys of an array
array_combine ā Creates an array by using one array for keys and another for its values
array_column ā Return the values from a single column in the input array
I have 2 multidimensional arrays and I want to get the 1st array where the value of [file] key in array 1 is equal to value of [folder_name] key in array 2
$arr1 = [
[
'is_dir' => '1',
'file' => 'hello member',
'file_lcase' => 'hello member',
'date' => '1550733362',
'size' => '0',
'permissions' => '',
'extension' => 'dir',
],
[
'is_dir' => '1',
'file' => 'in in test',
'file_lcase' => 'in in test',
'date' => '1550730845',
'size' => '0',
'permissions' => '',
'extension' => 'dir',
]
];
$arr2 = [
[
'dic_id' => '64',
'folder_name' => 'hello member',
'share_with' => '11',
],
[
'dic_id' => '65',
'folder_name' => 'hello inside',
'share_with' => '11',
],
[
'dic_id' => '66',
'folder_name' => 'in in test',
'share_with' => '11',
],
];
I have tried while looping 2 arrays and getting to one array but it is not success.
We can iterate both arrays inside each other to check until we have a match.
Please be aware that this shows only the first match. If you want to keep all matches you should use another helper array to store first array values that matches to second array.
foreach ($array1 as $key => $value) {
foreach ($array2 as $id => $item) {
if($value['file'] == $item['folder_name']){
// we have a match so we print out the first array element
print_r($array1[$key]);
break;
}
}
}
To avoid a double loop that gives a time complexity of O(nĀ²), you could first create the set of "folder_name" values (as keys), and then use that to filter the first array. Both these operations have a time complexity of O(n) which is certainly more efficient for larger arrays:
$result = [];
$set = array_flip(array_column($arr2, "folder_name"));
foreach ($arr1 as $elem) {
if (isset($set[$elem["file"]])) $result[] = $elem;
}
$result will have the elements of $arr1 that meet the requirement.
$arr1 = array();
$arr2 = array();
$arr3 = array();
$arr1[] = array('is_dir'=>'1','file'=>'hello member','file_lcase'=>'hello member','date'=>'1550733362','size'=>'0','permissions'=>'','extension'=>'dir');
$arr1[] = array('is_dir'=>'1','file'=>'in in test','file_lcase'=>'in in test','date'=>'1550730845','size'=>'0','permissions'=>'','extension'=>'dir');
$arr2[] = array('dic_id'=>'64','folder_name'=>'hello member','share_with'=>'11');
$arr2[] = array('dic_id'=>'65','folder_name'=>'hello member','share_with'=>'11');
$arr2[] = array('dic_id'=>'66','folder_name'=>'in in test','share_with'=>'11');
foreach($arr1 as $a){
foreach($arr2 as $a2){
if($a['file'] == $a2['folder_name']){
$arr3[]=$a;
}
}
}
$arr3 = array_map("unserialize", array_unique(array_map("serialize", $arr3))); // remove duplicates
var_dump($arr3);
$arr3 contains the resultant array.
I am lost actually, not sure how to explain the question.
Suppose I have three array
$name = array('mark', 'jones', 'alex');
$age = array(12, 23, 34);
$country = array('USA', 'UK', 'Canada');
What I am looking for is:
array(
0 => array(
'name' => 'mark',
'age' => 12,
'country' => 'USA'
)
1 => array(
'name' => 'jones',
'age' => 23,
'country' => 'UK'
)
2 => array(
'name' => 'alex',
'age' => 34,
'country' => 'Canada'
);
Couldn't figure out any built in PHP array function to handle it.
try something like this
$result = array();
foreach($name as $key => $value)
{
$result[$key] = array (
'name' => $value,
'age' => $age[$key],
'country' => $country[$key]
);
}
echo '<pre>';
print_r($result);
?>
You could do it without any manual looping like this:
// array_map with null callback merges corresponding items from each input
$merged = array_map(null, $name, $age, $country);
// walk over the results to change array_map's numeric keys to strings
$keys = ['name', 'age', 'country'];
array_walk(
$merged,
function(&$row) { $row = array_combine(['name', 'age', 'country'], $row); }
);
print_r($merged);
You can even write it in such a way that the keys in the result are equal to the names of the variables $name, $age, $country without needing to repeat yourself:
// Here "name", "age" and "country" appear only once:
$inputs = compact('name', 'age', 'country');
$merged = call_user_func_array('array_map', [null] + $inputs);
$keys = array_keys($inputs);
array_walk(
$merged,
function(&$row) use($keys) { $row = array_combine($keys, $row); }
);
However, to be frank it might be more readable (and it might even be faster) to just for over the inputs (assuming they have the same number of items) and do it manually.
I have two arrays, both have the same keys (different values) however array #2 is in a different order. I want to be able to resort the second array so it is in the same order as the first array.
Is there a function that can quickly do this?
I can't think of any off the top of my head, but if the keys are the same across both arrays then why not just loop over the first one and use its key order to create a new array using the the values from the 2nd one?
$arr1 = array(
'a' => '42',
'b' => '551',
'c' => '512',
'd' => 'gge',
) ;
$arr2 = array(
'd' => 'ordered',
'b' => 'is',
'c' => 'now',
'a' => 'this',
) ;
$arr2ordered = array() ;
foreach (array_keys($arr1) as $key) {
$arr2ordered[$key] = $arr2[$key] ;
}
You can use array_replace
$arr1 = [
'x' => '42',
'y' => '551',
'a' => '512',
'b' => 'gge',
];
$arr2 = [
'a' => 'ordered',
'x' => 'this',
'y' => 'is',
'b' => 'now',
];
$arr2 = array_replace($arr1, $arr2);
$arr2 is now
[
'x' => this,
'y' => is,
'a' => ordered,
'b' => now,
]
foreach(array_keys($array1) as $key)
{
$tempArray[$key] = $array2[$key];
}
$array2 = $tempArray;
I am not completely sure if this is what your after. anyways as long as the the array remains the same size, than this should work for you.
$gamey = array ("wow" => "World of Warcraft", "gw2" => "Guild Wars2", "wiz101" => "Wizard 101");
$gamex = array ("gw2" => "best game", "wiz101" => "WTF?", "wow" => "World greatest");
function match_arrayKeys ($x, $y)
{
$keys = array_keys ($x);
$values = array_values ($y);
for ($x = 0; $x < count ($keys); $x++)
{
$newarray [$keys[$x]] = $y[$keys[$x]];
}
return $newarray;
}
print_r (match_arrayKeys ($gamey, $gamex));
Output
[wow] => World greatest
[gw2] => best game
[wiz101] => WTF?
Try this
CODE
$fruits = array("d"=>"lemon", "a"=>"orange", "b"=>"banana", "c"=>"apple");
ksort($fruits);
foreach ($fruits as $key => $val) {
echo "$key = $val\n";
}
OUTPUT
a = orange
b = banana
c = apple
d = lemon
Check the php manual for ksort()
I have an array like below
$old = array(
'a' => 'blah',
'b' => 'key',
'c' => 'amazing',
'd' => array(
0 => 'want to replace',
1 => 'yes I want to'
)
);
I have another array having keys to replace with key information.
$keyReplaceInfoz = array('a' => 'newA', 'b' => 'newB', 'c' => 'newC', 'd' => 'newD');
I need to replace all keys of array $old with respective values in array $keyReplaceInfo.
Output should be like this
$old = array(
'newA' => 'blah',
'newB' => 'key',
'newC' => 'amazing',
'newD' => array(
0 => 'want to replace',
1 => 'yes I want to'
)
);
I had to do it manually as below. I am expecting better option. can anyone suggest better way to accomplish this?
$new = array();
foreach ($old as $key => $value)
{
$new[$keyReplaceInfoz[$key]] = $value;
}
I know this can be more simpler.
array_combine(array_merge($old, $keyReplaceInfoz), $old)
I think this looks easier than what you posed.
array_combine(
['newKey1', 'newKey2', 'newKey3'],
array_values(['oldKey1' => 1, 'oldKey2' => 2, 'oldKey3' => 3])
);
This should do the trick as long as you have the same number of values and the same order.
IMO using array_combine, array_merge, even array_intersect_key is overkill.
The original code is good enough, and very fast.
Adapting #shawn-k solution, here is more cleaner code using array_walk, it will only replace desired keys, of course you can modify as per your convenience
array_walk($old, function($value,$key)use ($keyReplaceInfoz,&$old){
$newkey = array_key_exists($key,$keyReplaceInfoz)?$keyReplaceInfoz[$key]:false;
if($newkey!==false){$old[$newkey] = $value;unset($old[$key]);
}
});
print_r($old);
I just solved this same problem in my own application, but for my application $keyReplaceInfoz acts like the whitelist- if a key is not found, that whole element is removed from the resulting array, while the matching whitelisted keys get translated to the new values.
I suppose you could apply this same algorithm maybe with less total code by clever usage of array_map (http://php.net/manual/en/function.array-map.php), which perhaps another generous reader will do.
function filterOldToAllowedNew($key_to_test){
return isset($keyReplaceInfoz[$key_to_test])?$keyReplaceInfoz[$key_to_test]:false;
}
$newArray = array();
foreach($old as $key => $value){
$newkey = filterOldToAllowedNew($key);
if($newkey){
$newArray[$newkey] = $value;
}
}
print_r($newArray);
This question is old but since it comes up first on Google I thought I'd add solution.
// Subject
$old = array('foo' => 1, 'baz' => 2, 'bar' => 3));
// Translations
$tr = array('foo'=>'FOO', 'bar'=>'BAR');
// Get result
$new = array_combine(preg_replace(array_map(function($s){return "/^$s$/";},
array_keys($tr)),$tr, array_keys($old)), $old);
// Output
print_r($new);
Result:
Array
(
[FOO] => 1
[baz] => 2
[BAR] => 3
)
This the solution i have implemented for the same subject:
/**
* Replace keys of given array by values of $keys
* $keys format is [$oldKey=>$newKey]
*
* With $filter==true, will remove elements with key not in $keys
*
* #param array $array
* #param array $keys
* #param boolean $filter
*
* #return $array
*/
function array_replace_keys(array $array,array $keys,$filter=false)
{
$newArray=[];
foreach($array as $key=>$value)
{
if(isset($keys[$key]))
{
$newArray[$keys[$key]]=$value;
}
elseif(!$filter)
{
$newArray[$key]=$value;
}
}
return $newArray;
}
This works irrespective of array order & array count. Output order & value will be based on replaceKey.
$replaceKey = array('a' => 'newA', 'b' => 'newB', 'c' => 'newC', 'd' => 'newD', 'e' => 'newE','f'=>'newF');
$array = array(
'a' => 'blah',
'd' => array(
0 => 'want to replace',
1 => 'yes I want to'
),
'noKey'=>'RESIDUAL',
'c' => 'amazing',
'b' => 'key',
);
$filterKey = array_intersect_key($replaceKey,$array);
$filterarray = array_intersect_key(array_merge($filterKey,$array),$filterKey);
$replaced = array_combine($filterKey,$filterarray);
//output
var_export($replaced);
//array ( 'newA' => 'blah', 'newB' => 'key', 'newC' => 'amazing', 'newD' => array ( 0 => 'want to replace', 1 => 'yes I want to' ) )
If you're looking for a recursive solution to use on a multidimensional array, have a look at the below method. It will replace all keys requested, and leave all other keys alone.
/**
* Given an array and a set of `old => new` keys,
* will recursively replace all array keys that
* are old with their corresponding new value.
*
* #param mixed $array
* #param array $old_to_new_keys
*
* #return array
*/
function array_replace_keys($array, array $old_to_new_keys)
{
if(!is_array($array)){
return $array;
}
$temp_array = [];
$ak = array_keys($old_to_new_keys);
$av = array_values($old_to_new_keys);
foreach($array as $key => $value){
if(array_search($key, $ak, true) !== false){
$key = $av[array_search($key, $ak)];
}
if(is_array($value)){
$value = array_replace_keys($value, $old_to_new_keys);
}
$temp_array[$key] = $value;
}
return $temp_array;
}
Using OP's example array:
$old = array(
'a' => 'blah',
'b' => 'key',
'c' => 'amazing',
'd' => array(
0 => 'want to replace',
1 => 'yes I want to'
)
);
$replace = ["a" => "AA", 1 => 11];
var_export(array_replace_keys($old, $replace));
Gives the following output:
array (
'AA' => 'blah',
'b' => 'key',
'c' => 'amazing',
'd' =>
array (
0 => 'want to replace',
11 => 'yes I want to',
),
)
DEMO
Inspired by the following snippet.
This uses #Summoner's example but keeps #Leigh's hint in mind:
$start = microtime();
$array = [ "a" => 1, "b" => 2, "c" => 3 ];
function array_replace_key($array, $oldKey, $newKey) {
$keys = array_keys($array);
$idx = array_search($oldKey, $keys);
array_splice($keys, $idx, 1, $newKey);
return array_combine($keys, array_values($array));
}
print_r(array_replace_key($array, "b", "z"));
<?php
$new = array();
foreach ($old as $key => $value)
{
$new[$keyReplaceInfoz][$key] = $value;
}
?>