I have an array named $arr = array. Some of its keys has value, like this:
$arr['1'] = 'one';
$arr['2'] = 'two';
$arr['3'] = 'three';
Now I initialize that array with another arry, some thing like this:
$arr = array('4' => 'four', '5' => 'five');
But I need to keep the previous values. I mean is, when I print that array, the output will be like this:
echo '<pre>';
print_r($arr);
/* ---- output:
Array
(
[4] => four
[5] => five
)
*/
While I want this output:
Array
(
[1] => one
[2] => two
[3] => three
[4] => four
[5] => five
)
So, How can I take care of old keys (values) after re-initialized?
Here are your options detailed below: array_merge, union (+ operator), array_push, just set the keys directly and make a function that just loops over the array with your own custom rules.
Sample data:
$test1 = array('1'=>'one', '2'=>'two', '3'=>'three', 'stringkey'=>'string');
$test2 = array('3'=>'new three', '4'=>'four', '5'=>'five', 'stringkey'=>'new string');
array_merge (as seen in other answers) will re-index numeric keys (even numeric strings) back to zero and append new numeric indexes to the end. Non numeric string indexes will overwrite the value where the index exists in the former array with the value of the latter array.
$combined = array_merge($test1, $test2);
Result (http://codepad.viper-7.com/c9QiPe):
Array
(
[0] => one
[1] => two
[2] => three
[stringkey] => new string
[3] => new three
[4] => four
[5] => five
)
A union will combine the arrays but both string and numeric keys will be handled the same. New indexes will be added and existing indexes will NOT be overwritten.
$combined = $test1 + $test2;
Result (http://codepad.viper-7.com/8z5g26):
Array
(
[1] => one
[2] => two
[3] => three
[stringkey] => string
[4] => four
[5] => five
)
array_push allows you to append keys to an array. So as long as the new keys are numeric and in sequential order, you can push on to the end of the array. Note though, non-numeric string keys in the latter array will be re-indexed to the highest numeric index in the existing array +1. If there are no numeric keys, this would be zero. You would also need to reference each new value as a separate argument (see arguments two and three below). Also, since the first argument is taken in by reference, it will modify the original array. The other options allow you to combine to a separate array in case you need the original.
array_push($test1, 'four', 'five');
Result (http://codepad.viper-7.com/5b9nvC):
Array
(
[1] => one
[2] => two
[3] => three
[stringkey] => string
[4] => four
[5] => five
)
You could also just set the keys directly.
$test1['4'] = 'four';
$test1['5'] = 'five';
Or even just make a loop and wrap it in a function to handle your custom rules for merging
function custom_array_merge($arr1, $arr2){
//loop over array 2
foreach($arr2 as $k=>$v){
//if key exists in array 1
if(array_key_exists($arr1, $k)){
//do something special for when key exists
} else {
//do something special for when key doesn't exists
$arr1[$k] = $v;
}
}
return $arr1;
}
The function could be expanded to use stuff like func_get_args to allow any number of arguments.
I'm sure there are also more "hacky" ways to do it using stuff like array_
splice or other array functions. However, IMO, I would avoid them just to keep the code a little more clear about what you are doing.
use array_merge:
$arr = array_merge($arr, array('4' => 'four', '5' => 'five'));
Well, as per the comments (which are correct) this will reindex the array, another solution to avoid that would be to do as follows:
array_push($arr, "four", "five");
But this would not work if you have different keys, like strings that are not masked numbers.
Another way is to use + in order to merge them maintaining keys:
$arr['1'] = 'one';
$arr['2'] = 'two';
$arr['3'] = 'three';
$arr2 = array('4' => 'four', '5' => 'five');
$arr = $arr + $arr2;
Another way to do it, and keeps the keys of the array, is using array_replace.
$arr['1'] = 'one';
$arr['2'] = 'two';
$arr['3'] = 'three';
print_r(array_replace($arr, array('4' => 'four', '5' => 'five')));
Output:
Array
(
[1] => one
[2] => two
[3] => three
[4] => four
[5] => five
)
Related
I have an array with some values (numeric values):
$arr1 = [1, 3, 8, 12, 23]
and I have another associative array that a key (which matches to a value of $arr1) correspond to a value. This array may contain also keys that don't match with $arr1.
$arr2 = [1 => "foo", 2 => "foo98", 3 => "foo20", 8 => "foo02", 12 => "foo39", 15 => "foo44", 23 => "foo91", 34 => "foo77"]
I want as return the values of $arr2 specifying as key the values of $arr1:
["foo", "foo20", "foo02", "foo39", "foo91"]
If possible, all this, without loops, using just PHP array native functions (so in an elegant way), or at least with the minimum number of loops possible.
Minimal loop is simple - 1. as:
foreach($arr1 as $k) {
$res[] = $arr2[$k];
}
You can do that with array_walk but I think this simple way is more readable.
If you insist you can do with array_filter + array_values + in_array as:
$res = array_values(array_filter($arr2,
function ($key) use ($arr1) { return in_array($key, $arr1);},
ARRAY_FILTER_USE_KEY
));
You can see this for more about filtering keys
To do it purely with array functions, you could do it as...
print_r(array_intersect_key($arr2, array_flip($arr1) ));
So array_flip() turns the items you want form the array into the keys for $arr1 and then uses array_intersect_key() to match the keys with the main array and this newly created array.
Gives...
Array
(
[1] => foo
[3] => foo20
[8] => foo02
[12] => foo39
[23] => foo91
)
If you don't want the keys - add array_values() around the rest of the calls...
print_r(array_values(array_intersect_key($arr2, array_flip($arr1) )));
to get
Array
(
[0] => foo
[1] => foo20
[2] => foo02
[3] => foo39
[4] => foo91
)
Although as pointed out - sometimes a simple foreach() is just as good and sometimes better.
Very simplified example:
function returnArray() {
return array('First','Second','Third');
}
$arr = array('hello','world');
$arr[] = returnArray();
print_r($arr);
I was (wrongly) expecting to see $arr containing 5 elements, but it actually contains this (and I understand it makes sense):
Array
(
[0] => hello
[1] => world
[2] => Array
(
[0] => First
[1] => Second
[2] => Third
)
)
Easily enough, I "fixed" it using a temporary array, scanning through its elements, and adding the elements one by one to the $arr array.
But I guess/hope that there must be a way to tell PHP to add the elements automatically one by one, instead of creating a "child" array within the first one, right? Thanks!
You can use array_merge,
$arr = array_merge($arr, returnArray());
will result in
Array
(
[0] => hello
[1] => world
[2] => First
[3] => Second
[4] => Third
)
This will work smoothly here, since your arrays both have numeric keys. If the keys were strings, you’d had to be more careful (resp. decide if that would be the result you want, or not), because
If the input arrays have the same string keys, then the later value for that key will overwrite the previous one. If, however, the arrays contain numeric keys, the later value will not overwrite the original value, but will be appended.
You are appending the resulting array to previously created array. Instead of the use array merge.
function returnArray() {
return array('First','Second','Third');
}
$arr = array('hello','world');
$arr = array_merge($arr, returnArray());
print_r($arr);
I have two arrays (in PHP):
ArrayA
(
[0] => 9
[1] => 1
[2] => 2
[3] => 7
)
ArrayB
(
[0] => 1
[1] => 1
[3] => 8
)
I want to make two new arrays, where I have only the elements declared in both of the arrays, like the following:
ArrayA
(
[0] => 9
[1] => 1
[3] => 7
)
ArrayB
(
[0] => 1
[1] => 1
[3] => 8
)
In this example ArrayA[2] doesn't exist, so ArrayB[2] has been unset.
I wrote this for loop:
for ($i = 0, $i = 99999, $i++){
if (isset($ArrayA[$i]) AND isset($ArrayB[$i]) == FALSE)
{
unset($ArrayA[$i],$ArrayB[$i]);
}
}
But it's not great because it tries every index between 0 and a very big number (99999 in this case). How can I improve my code?
The function you're looking for is array_intersect_key:
array_intersect_key() returns an array containing all the entries of array1 which have keys that are present in all the arguments.
Since you want both arrays, you'll have to run it twice, with the parameters in opposite orders, as it only keeps keys from the first array. An example:
$arrayA_filtered = array_intersect_key($arrayA, $arrayB);
$arrayB_filtered = array_intersect_key($arrayB, $arrayA);
Also, although a for loop wasn't ideal in this case, in other cases where you find yourself needing to loop through sparse array (one where not every number is set), you can use a foreach loop:
foreach($array as $key => $value) {
//Do stuff
}
One very important thing to note about PHP arrays is that they are associative. You can't simply use a for loop, as the indices are not necessarily a range of integers. Consider what would happen if you applied this algorithm twice! You'd get out of bounds errors as $arrayA[2] and $arrayB[2] no longer exist!
I would iterate through the arrays using nested foreach statements. I.e.
$outputA = array();
$outputB = array();
foreach ($arrayA as $keyA => $itemA) {
foreach ($arrayB as $keyB => $itemB) {
if ($keyA == $keyB) {
$outputA[$keyA] = $itemA;
$outputB[$keyB] = $itemB;
}
}
This should give you two arrays, $outputA and $outputB, which look just like $arrayA and $arrayB, except they only include key=>value pairs if the key was present in both original arrays.
foreach($arrayA as $k=>$a)
if (!isset($arrayB[$k]))
unset($arrayA[$k];
Take a look to php : array_diff
http://docs.php.net/manual/fr/function.array-diff.php
I have an array with 3 values:
$b = array('A','B','C');
This is what the original array looks like:
Array ( [0] => A [1] => B [2] => C )
I would like to insert a specific value(For example, the letter 'X') at the position between the first and second key, and then shift all the values following it down one. So in effect it would become the 2nd value, the 2nd would become the 3rd, and the 3rd would become the 4th.
This is what the array should look like afterward:
Array ( [0] => A [1] => X [2] => B [3] => C )
How do I insert a value in between two keys in an array using php?
array_splice() is your friend:
$arr = array('A','B','C');
array_splice($arr, 1, 0, array('X'));
// $arr is now array('A','X','B','C')
This function manipulates arrays and is usually used to truncate an array. However, if you "tell it" to delete zero items ($length == 0), you can insert one or more items at the specified index.
Note that the value(s) to be inserted have to be passed in an array.
There is a way without the use of array_splice. It is simpler, however, more dirty.
Here is your code:
$arr = array('A', 'B', 'C');
$arr['1.5'] = 'X'; // '1.5' should be a string
ksort($arr);
The output:
Array
(
[0] => A
[1] => B
[1.5] => X
[2] => C
)
This question already has answers here:
Merging two arrays with the "+" (array union operator) How does it work?
(9 answers)
Closed 9 years ago.
What is the best way to add two associative arrays such that duplicate values are not over written : + or array_ merge ?
I was pretty sure that using + operator I can add two associative arrays such that duplicate values are not over written but this Answer is saying something different and so am not sure if it is really true.
I would really appreciate if you can share some lights on how can we add two associative arrays such that duplicate values are not over written.
Appreciate your time and responses.
An array can't have more than one key-value pair with the same key. So if you have:
$array1 = array(
'foo' => 5,
'bar' => 10,
'baz' => 6
);
$array2 = array(
'x' => 100,
'y' => 200,
'baz' => 30
);
If you combine these arrays, you only get to keep one of the values of the combined array. The methods you describe do two different things:
print_r(($array1 + $array2));
// Result:
// Array
// (
// [foo] => 5
// [bar] => 10
// [baz] => 6
// [x] => 100
// [y] => 200
// )
print_r(array_merge($array1, $array2));
// Result:
// Array
// (
// [foo] => 5
// [bar] => 10
// [baz] => 30
// [x] => 100
// [y] => 200
// )
So you really need to define what you want to happen when you combine the arrays.
UPDATE
Based on #davidosomething's answer, here's what happens if you do array_merge_recursive():
print_r(array_merge_recursive($array1, $array2));
// Result:
// Array
// (
// [foo] => 5
// [bar] => 10
// [baz] => Array
// (
// [0] => 6
// [1] => 30
// )
//
// [x] => 100
// [y] => 200
// )
You actually want array_merge_recursive
This creates an array of arrays if the KEY is the same but the value is different
Both array_merge and union will DISCARD one of the VALUES if a duplicate key is found
If you want to keep both values, you have to change the key for at least one of them. Perhaps you can write your own method to merge two arrays which prefixes all keys.
array_merge will combine the arrays such that no values are lost, provided the arrays have contiguous numeric keys. If you start mixing string keys, values with the same keys will be overwritten. If you treat your arrays as arrays and not maps, array_merge will do what you want.
a picture is better than 1000 words
$a = array('foo' => 'A');
$b = array('foo' => 'B');
print_r($a + $b); // foo=A
print_r(array_merge($a, $b)); // foo=B