Array1
(
[a]=>1; [b]=>2; [c]=>3
)
Array2
(
[a]=>1;[b] =>1
)
Required result:
Array1
(
[a]=>2; [b]=>3; [c]=>3
)
How do i append Array1 with the values of Array2 based on their key? Thanks.
You can try something like this:
foreach($array2 as $key2 => $val2){
if(key_exists($key2, $array1)) {
$array1[$key2] += $val2;
} else {
$array1[$key2] = $val2;
}
}
Part of the issue would be that array 1 may not have all of the same keys as array 2. So, an array of all keys from both original arrays is needed, then loop through those keys, check if it exists in either original array, and finally add it to the final combined array.
<?php
$array1 = array('a' => 1, 'b' => 2, 'c' => 3);
$array2 = array('a' => 1, 'b' => 2, 'd' => 3);
$finalarr = array();
$arrkeys = array_merge(array_keys($array1), array_keys($array2));
$arrkeys = array_unique($arrkeys);
foreach($arrkeys as $key) {
$finalarr[$key] = 0;
if (isset($array1[$key])) {
$finalarr[$key] += $array1[$key];
}
if (isset($array2[$key])) {
$finalarr[$key] += $array2[$key];
}
}
print_r($finalarr);
?>
foreach($array1 as $key=>$value){
if(isset($array2[$key])){
$array1[$key] = $array1[$key] + $array2[$key];
}
}
Not the most elegant way, which would use array_walk or array_map, but I like to see and know exactly what's going on. This will give you what you are looking for.
First sum the values of the common keys and after that, add the others key in the other array:
foreach ($array2 as $k2 => $a2){
if (isset($array1[$k2])){
$array1[$k2]+=$a2;
unset($array2[$k2]);
}
}
$array1 += $array2;
Something like:
$result = array();
function ParseArray(array $array, array &$result)
{
foreach ($array as $k => $v) {
if (!array_key_exists($k, $result) {
$result[$k] = $v;
} else {
$result[$k] += $v;
}
}
}
ParseArray($Array1, $result);
ParseArray($Array2, $result);
print_r($result);
You should read about PHP array functions.
$array1 = array(
'a' => 1,
'b' => 2,
'c' => 3,
);
$array2 = array(
'a' => 1,
'b' => 1,
);
array_walk(
$array1,
function (&$value, $key) use ($array2) {
$value += (isset($array2[$key])) ? $array2[$key] : 0;
}
);
var_dump($array1);
Is there any function in PHP which will give an array of uncommon values from two or more arrays?
For example:
$array1 = array( "green", "red", "blue");
$array2 = array( "green", "yellow", "red");
....
$result = Function_Needed($array1, $array2,...);
print_r($result);
Should give the output:
array("blue", "yellow", ...);
Use array_diff and array_merge:
$result = array_merge(array_diff($array1, $array2), array_diff($array2, $array1));
Here's a demo.
For multiple arrays, combine it with a callback and array_reduce:
function unique(&$a, $b) {
return $a ? array_merge(array_diff($a, $b), array_diff($b, $a)) : $b;
}
$arrays = array(
array('green', 'red', 'blue'),
array('green', 'yellow', 'red')
);
$result = array_reduce($arrays, 'unique');
And here's a demo of that.
$result = array_diff($array1, $array2) + array_diff($array2, $array1);
Try array_diff.
This should do it. It can be extended to work with more than two arrays. It basically counts the common key occurrences and returns those with count of one:
$a = array('yellow', 'blue', 'red', 'green');
$b = array('blue', 'purple', 'green');
function unintersect($a, $b)
{
$x = array_fill_keys($a, 1);
foreach ($b as $v) {
$x[$v]++; // this might trigger warning
}
return array_keys(array_filter($x, function($v) {
return $v === 1;
}));
}
print_r(unintersect($a, $b));
Returns:
Array
(
[0] => yellow
[1] => red
[2] => purple
)
i want to check if one array is contained in the second array ,
but the same key and the same values,
(not need to be equal, only check that all the key and value in one array is in the second)
the simple thing that i do until now is :
function checkSameValues($a, $b){
foreach($a as $k1 => $v1){
if($v1 && $v1 != $b[$k1]){
return false;
break;
}
}
return true;
}
Is there a simpler(faster) way to check this ?
thanks
I would do
$array1 = array("a" => "green", "b" => "blue", "c" => "white", "d" => "red");
$array2 = array("a" => "green", "b" => "blue", "d" => "red");
$result = array_diff_assoc($array2, $array1);
if (!count($result)) echo "array2 is contained in array";
What about...
$intersect = array_intersect_assoc($a, $b);
if( count($intersect) == count($b) ){
echo "yes, it's inside";
}
else{
echo "no, it's not.";
}
array_intersect_assoc
array_intersect_assoc() returns an array containing all the values of array1 that are present in all the arguments.
function checkSameValues($a, $b){
if ( in_array($a,$b) ) return true;
else return false;
}
This obviously only checks depth=1, but could easily be adapted to be recursive:
// check if $a2 is contained in $a1
function checkSameValues($a1, $a2)
{
foreach($a1 as $element)
{
if($element == $a2) return true;
}
return false;
}
$a1 = array('foo' => 'bar', 'bar' => 'baz');
$a2 = array('el' => 'one', 'another' => $a1);
var_dump(checkSameValues($a2, $a1)); // true
Example:
$arr = array(
'apple' => 'sweet',
'grapefruit' => 'bitter',
'pear' => 'tasty',
'banana' => 'yellow'
);
I want to switch the positions of grapefruit and pear, so the array will become
$arr = array(
'apple' => 'sweet',
'pear' => 'tasty',
'grapefruit' => 'bitter',
'banana' => 'yellow'
)
I know the keys and values of the elements I want to switch, is there an easy way to do this? Or will it require a loop + creating a new array?
Thanks
Just a little shorter and less complicated than the solution of arcaneerudite:
<?php
if(!function_exists('array_swap_assoc')) {
function array_swap_assoc($key1, $key2, $array) {
$newArray = array ();
foreach ($array as $key => $value) {
if ($key == $key1) {
$newArray[$key2] = $array[$key2];
} elseif ($key == $key2) {
$newArray[$key1] = $array[$key1];
} else {
$newArray[$key] = $value;
}
}
return $newArray;
}
}
$array = $arrOrig = array(
'fruit' => 'pear',
'veg' => 'cucumber',
'tuber' => 'potato',
'meat' => 'ham'
);
$newArray = array_swap_assoc('veg', 'tuber', $array);
var_dump($array, $newArray);
?>
Tested and works fine
Here's my version of the swap function:
function array_swap_assoc(&$array,$k1,$k2) {
if($k1 === $k2) return; // Nothing to do
$keys = array_keys($array);
$p1 = array_search($k1, $keys);
if($p1 === FALSE) return; // Sanity check...keys must exist
$p2 = array_search($k2, $keys);
if($p2 === FALSE) return;
$keys[$p1] = $k2; // Swap the keys
$keys[$p2] = $k1;
$values = array_values($array);
// Swap the values
list($values[$p1],$values[$p2]) = array($values[$p2],$values[$p1]);
$array = array_combine($keys, $values);
}
if the array comes from the db, add a sort_order field so you can always be sure in what order the elements are in the array.
This may or may not be an option depending on your particular use-case, but if you initialize your array with null values with the appropriate keys before populating it with data, you can set the values in any order and the original key-order will be maintained. So instead of swapping elements, you can prevent the need to swap them entirely:
$arr = array('apple' => null,
'pear' => null,
'grapefruit' => null,
'banana' => null);
...
$arr['apple'] = 'sweet';
$arr['grapefruit'] = 'bitter'; // set grapefruit before setting pear
$arr['pear'] = 'tasty';
$arr['banana'] = 'yellow';
print_r($arr);
>>> Array
(
[apple] => sweet
[pear] => tasty
[grapefruit] => bitter
[banana] => yellow
)
Not entirely sure if this was mentioned, but, the reason this is tricky is because it's non-indexed.
Let's take:
$arrOrig = array(
'fruit'=>'pear',
'veg'=>'cucumber',
'tuber'=>'potato'
);
Get the keys:
$arrKeys = array_keys($arrOrig);
print_r($arrKeys);
Array(
[0]=>fruit
[1]=>veg
[2]=>tuber
)
Get the values:
$arrVals = array_values($arrOrig);
print_r($arrVals);
Array(
[0]=>pear
[1]=>cucumber
[2]=>potato
)
Now you've got 2 arrays that are numerical. Swap the indices of the ones you want to swap, then read the other array back in in the order of the modified numerical array. Let's say we want to swap 'fruit' and 'veg':
$arrKeysFlipped = array_flip($arrKeys);
print_r($arrKeysFlipped);
Array (
[fruit]=>0
[veg]=>1
[tuber]=>2
)
$indexFruit = $arrKeysFlipped['fruit'];
$indexVeg = $arrKeysFlipped['veg'];
$arrKeysFlipped['veg'] = $indexFruit;
$arrKeysFlipped['fruit'] = $indexVeg;
print_r($arrKeysFlipped);
Array (
[fruit]=>1
[veg]=>0
[tuber]=>2
)
Now, you can swap back the array:
$arrKeys = array_flip($arrKeysFlipped);
print_r($arrKeys);
Array (
[0]=>veg
[1]=>fruit
[2]=>tuber
)
Now, you can build an array by going through the oringal array in the 'order' of the rearranged keys.
$arrNew = array ();
foreach($arrKeys as $index=>$key) {
$arrNew[$key] = $arrOrig[$key];
}
print_r($arrNew);
Array (
[veg]=>cucumber
[fruit]=>pear
[tuber]=>potato
)
I haven't tested this - but this is what I'd expect. Does this at least provide any kind of help? Good luck :)
You could put this into a function $arrNew = array_swap_assoc($key1,$key2,$arrOld);
<?php
if(!function_exists('array_swap_assoc')) {
function array_swap_assoc($key1='',$key2='',$arrOld=array()) {
$arrNew = array ();
if(is_array($arrOld) && count($arrOld) > 0) {
$arrKeys = array_keys($arrOld);
$arrFlip = array_flip($arrKeys);
$indexA = $arrFlip[$key1];
$indexB = $arrFlip[$key2];
$arrFlip[$key1]=$indexB;
$arrFlip[$key2]=$indexA;
$arrKeys = array_flip($arrFlip);
foreach($arrKeys as $index=>$key) {
$arrNew[$key] = $arrOld[$key];
}
} else {
$arrNew = $arrOld;
}
return $arrNew;
}
}
?>
WARNING: Please test and debug this before just using it - no testing has been done at all.
There is no easy way, just a loop or a new array definition.
Classical associative array doesn't define or guarantee sequence of elements in any way. There is plain array/vector for that. If you use associative array you are assumed to need random access but not sequential. For me you are using assoc array for task it is not made for.
yeah I agree with Lex, if you are using an associative array to hold data, why not using your logic handle how they are accessed instead of depending on how they are arranged in the array.
If you really wanted to make sure they were in a correct order, trying creating fruit objects and then put them in a normal array.
There is no easy way to do this. This sounds like a slight design-logic error on your part which has lead you to try to do this when there is a better way to do whatever it is you are wanting to do. Can you tell us why you want to do this?
You say that I know the keys and values of the elements I want to switch which makes me think that what you really want is a sorting function since you can easily access the proper elements anytime you want as they are.
$value = $array[$key];
If that is the case then I would use sort(), ksort() or one of the many other sorting functions to get the array how you want. You can even use usort() to Sort an array by values using a user-defined comparison function.
Other than that you can use array_replace() if you ever need to swap values or keys.
Here are two solutions. The first is longer, but doesn't create a temporary array, so it saves memory. The second probably runs faster, but uses more memory:
function swap1(array &$a, $key1, $key2)
{
if (!array_key_exists($key1, $a) || !array_key_exists($key2, $a) || $key1 == $key2) return false;
$after = array();
while (list($key, $val) = each($a))
{
if ($key1 == $key)
{
break;
}
else if ($key2 == $key)
{
$tmp = $key1;
$key1 = $key2;
$key2 = $tmp;
break;
}
}
$val1 = $a[$key1];
$val2 = $a[$key2];
while (list($key, $val) = each($a))
{
if ($key == $key2)
$after[$key1] = $val1;
else
$after[$key] = $val;
unset($a[$key]);
}
unset($a[$key1]);
$a[$key2] = $val2;
while (list($key, $val) = each($after))
{
$a[$key] = $val;
unset($after[$key]);
}
return true;
}
function swap2(array &$a, $key1, $key2)
{
if (!array_key_exists($key1, $a) || !array_key_exists($key2, $a) || $key1 == $key2) return false;
$swapped = array();
foreach ($a as $key => $val)
{
if ($key == $key1)
$swapped[$key2] = $a[$key2];
else if ($key == $key2)
$swapped[$key1] = $a[$key1];
else
$swapped[$key] = $val;
}
$a = $swapped;
return true;
}
fwiw here is a function to swap two adjacent items to implement moveUp() or moveDown() in an associative array without foreach()
/**
* #param array $array to modify
* #param string $key key to move
* #param int $direction +1 for down | -1 for up
* #return $array
*/
protected function moveInArray($array, $key, $direction = 1)
{
if (empty($array)) {
return $array;
}
$keys = array_keys($array);
$index = array_search($key, $keys);
if ($index === false) {
return $array; // not found
}
if ($direction < 0) {
$index--;
}
if ($index < 0 || $index >= count($array) - 1) {
return $array; // at the edge: cannot move
}
$a = $keys[$index];
$b = $keys[$index + 1];
$result = array_slice($array, 0, $index, true);
$result[$b] = $array[$b];
$result[$a] = $array[$a];
return array_merge($result, array_slice($array, $index + 2, null, true));
}
There is an easy way:
$sourceArray = array(
'apple' => 'sweet',
'grapefruit' => 'bitter',
'pear' => 'tasty',
'banana' => 'yellow'
);
// set new order
$orderArray = array(
'apple' => '', //this values would be replaced
'pear' => '',
'grapefruit' => '',
//it is not necessary to touch all elemets that will remains the same
);
$result = array_replace($orderArray, $sourceArray);
print_r($result);
and you get:
$result = array(
'apple' => 'sweet',
'pear' => 'tasty',
'grapefruit' => 'bitter',
'banana' => 'yellow'
)
function arr_swap_keys(array &$arr, $key1, $key2, $f_swap_vals=false) {
// if f_swap_vals is false, then
// swap only the keys, keeping the original values in their original place
// ( i.e. do not preserve the key value correspondence )
// i.e. if arr is (originally)
// [ 'dog' => 'alpha', 'cat' => 'beta', 'horse' => 'gamma' ]
// then calling this on arr with, e.g. key1 = 'cat', and key2 = 'horse'
// will result in arr becoming:
// [ 'dog' => 'alpha', 'horse' => 'beta', 'cat' => 'gamma' ]
//
// if f_swap_vals is true, then preserve the key value correspondence
// i.e. in the above example, arr will become:
// [ 'dog' => 'alpha', 'horse' => 'gamma', 'cat' => 'beta' ]
//
//
$arr_vals = array_values($arr); // is a (numerical) index to value mapping
$arr_keys = array_keys($arr); // is a (numerical) index to key mapping
$arr_key2idx = array_flip($arr_keys);
$idx1 = $arr_key2idx[$key1];
$idx2 = $arr_key2idx[$key2];
swap($arr_keys[$idx1], $arr_keys[$idx2]);
if ( $f_swap_vals ) {
swap($arr_vals[$idx1], $arr_vals[$idx2]);
}
$arr = array_combine($arr_keys, $arr_vals);
}
function swap(&$a, &$b) {
$t = $a;
$a = $b;
$b = $t;
}
Well it's just a key sorting problem. We can use uksort for this purpose. It needs a key comparison function and we only need to know that it should return 0 to leave keys position untouched and something other than 0 to move key up or down.
Notice that it will only work if your keys you want to swap are next to each other.
<?php
$arr = array(
'apple' => 'sweet',
'grapefruit' => 'bitter',
'pear' => 'tasty',
'banana' => 'yellow'
);
uksort(
$arr,
function ($k1, $k2) {
if ($k1 == 'grapefruit' && $k2 == 'pear') return 1;
else return 0;
}
);
var_dump($arr);
I'll share my short version too, it works with both numeric and associative arrays.
array array_swap ( array $array , mixed $key1 , mixed $key2 [, bool $preserve_keys = FALSE [, bool $strict = FALSE ]] )
Returns a new array with the two elements swapped. It preserve original keys if specified. Return FALSE if keys are not found.
function array_swap(array $array, $key1, $key2, $preserve_keys = false, $strict = false) {
$keys = array_keys($array);
if(!array_key_exists($key1, $array) || !array_key_exists($key2, $array)) return false;
if(($index1 = array_search($key1, $keys, $strict)) === false) return false;
if(($index2 = array_search($key2, $keys, $strict)) === false) return false;
if(!$preserve_keys) list($keys[$index1], $keys[$index2]) = array($key2, $key1);
list($array[$key1], $array[$key2]) = array($array[$key2], $array[$key1]);
return array_combine($keys, array_values($array));
}
For example:
$arr = array_swap($arr, 'grapefruit', 'pear');
I wrote a function with more general purpose, with this problem in mind.
array with known keys
specify order of keys in a second array ($order array keys indicate key position)
function order_array($array, $order) {
foreach (array_keys($array) as $k => $v) {
$keys[++$k] = $v;
}
for ($i = 1; $i <= count($array); $i++) {
if (isset($order[$i])) {
unset($keys[array_search($order[$i], $keys)]);
}
if ($i === count($array)) {
array_push($keys, $order[$i]);
} else {
array_splice($keys, $i-1, 0, $order[$i]);
}
}
}
foreach ($keys as $key) {
$result[$key] = $array[$key];
}
return $result;
} else {
return false;
}
}
$order = array(1 => 'item3', 2 => 'item5');
$array = array("item1" => 'val1', "item2" => 'val2', "item3" => 'val3', "item4" => 'val4', "item5" => 'val5');
print_r($array); -> Array ( [item1] => val1 [item2] => val2 [item3] => val3 [item4] => val4 [item5] => val5 )
print_r(order_array($array, $order)); -> Array ( [item3] => val3 [item5] => val5 [item1] => val1 [item2] => val2 [item4] => val4 )
I hope this is relevant / helpful for someone
Arrays in php are ordered maps.
$arr = array('apple'=>'sweet','grapefruit'=>'bitter','
pear'=>'tasty','banana'=>'yellow');
doesn't mean that that the first element is 'apple'=>'sweet' and the last - 'banana'=>'yellow' just because you put 'apple' first and 'banana' last. Actually, 'apple'=>'sweet' will be the first and
'banana'=>'yellow' will be the second because of alphabetical ascending sort order.
How would I switch the sort order between ascending/descending in the following function? All it does is order a multidimensional array by a chosen field, and then by title.
$sortby = 'date';
$orderby = 'asc';
function sort($a, $b)
{
$retval = strnatcmp($a[$sortby], $b[$sortby]);
if(!$retval) return strnatcmp($a['title'], $b['title']);
return $retval;
}
uasort($jobs, 'sort');
There is no reverse option - you'd have to create a new sort function that returns the negative of your sort function.
Simple but inefficient:
function rsort($a, $b)
{
return -1 * sort($a, $b);
}
<?php
// Comparison function
function cmp($a, $b) {
if ($a == $b) {
return 0;
}
return ($a>$b) ? -1 : 1;
}
// Array to be sorted
$array = array('a' => 5.2, 'b' => 2.2, 'c' => 1.2, 'd' => 1.2,'f' => 5.5, 'g' => 1.2, 'h' => 6.2);
print_r($array);
// Sort and print the resulting array
uasort($array, 'cmp');
print_r($array);
?>