I use this code :
$new = array(
"123" => "a",
"456" => "b"
);
$old = array(
"123" => "a",
"456" => "b"
);
then the $new array become like this:
$new = array(
"456" => "b",
"123" => "c",
"789" => "e"
);
as you see the count of $new array increased and the order of elements changed and the value at key 123 also changed. I need to compare the $new array against the $old array and catch only the change made on the value at key 123 without caring about the order and the count of elements. I tried:
$result = array_diff( $new, $old );
print_r( $result );
output :
Array ( [123] => c [789] => e )
UPDATE. quite confusing. now I think we got it
$old = array(
"123" => "a",
"456" => "b"
);
$new = array(
"456" => "b",
"123" => "c", // catch this (element in old array that is changed)
"789" => "e"
);
$new2 = array();
foreach ($new as $key => $new_val)
{
if (isset($old[$key])) // belongs to old array?
{
if ($old[$key] != $new_val) // has changed?
$new2[$key] = $new[$key]; // catch it
}
}
// output $new2:
array (
123 => 'c',
)
You first of all want to have those elements of $new that are changed compared to $old (see array_diff_assoc):
$changed = array_diff_assoc($new, $old);
Of that result you want to have only those elements that have their key in $old (see array_intersect_key):
$result = array_intersect_key($changed, $old);
And that's it. You can wrap that into each other if it helps:
array_intersect_key(array_diff_assoc($new, $old), $old);
Result is:
array(1) {
[123] =>
string(1) "c"
}
Full example (Demo):
$old = array(
"123" => "a",
"456" => "b"
);
$new = array(
"456" => "b",
"123" => "c", // catch only the change made on the value at key 123
"789" => "e"
);
$changed = array_diff_assoc($new, $old);
$result = array_intersect_key($changed, $old);
var_dump($result);
Just a final note: There are many array functions in PHP. It's worth to go through the list and look what is fitting because most often you only need one or two of them to get things like these done.
You use this code for your requirements
<?php
function key_compare_func($key1, $key2)
{
if ($key1 == $key2)
return 0;
else if ($key1 > $key2)
return 1;
else
return -1;
}
$array1 = array('blue' => 1, 'red' => 2, 'green' => 3, 'purple' => 4);
$array2 = array('green' => 5, 'blue' => 6, 'yellow' => 7, 'cyan' => 8);
var_dump(array_intersect_ukey($array1, $array2, 'key_compare_func'));
?>
Related
Is there built-in function, or shorter way to extract elements into new array, as described here?
<?php
function arr_slice ($arr, $keys) {
$ret = array();
foreach ($keys as $k) { $ret[$k] = $arr[$k]; }
return $ret;
}
$array = array(
"a" => 1,
"b" => 2,
"c" => 3,
"d" => 4,
);
var_export(
arr_slice($array, array("x","d","b"))
);
output (key order matters)
array (
'x' => NULL,
'd' => 4,
'b' => 2,
)
I need help with an array problem.
First I have an array like you would receive from a sql query:
$aRows=array(
array("one" => 1, "two" => 2, "three" => 3, "a" => "4", "b" => "lala"),
array("one" => 1, "two" => 2, "three" => 3, "a" => "5", "b" => "lolo"),
array("one" => 1, "two" => 2, "three" => 3, "a" => "6", "b" => "lili")
)
Then I have another array which defines the hierarchy - lets say
$aArray=array("one", "two", "three");
Now I want to build a hierarchical associative array:
$newArray =
array(
"one" => array(
"two" => array(
"three" => array(
array("a" => "4", "b" => "lala"),
array("a" => "5", "b" => "lolo"),
array("a" => "6", "b" => "lili"),
)
)
)
);
Imagine a "grouped by" sql and I want the hierarchical representation.
EDIT: In the sample one,two,three contains the same values, this would not be the case in real life - assume:
select one,two,three,a,b from a_table group by one,two,three;
Of course SQL will group equals values in one,two,three together and this redundant information is useless. But sql can not display hierarchic data, so the fields are redundant.
EDIT 2: Thanks to Waygood the complete solution is:
$aRows=array(
array("one" => 1, "two" => 2, "three" => 3, "a" => "4", "b" => "lala"),
array("one" => 1, "two" => 2, "three" => 4, "a" => "5", "b" => "lolo"),
array("one" => 1, "two" => 2, "three" => 4, "a" => "6", "b" => "lili")
);
$aArray=array("one", "two", "three");
$output=array();
foreach($aRows as $row)
{
$newKey = "";
foreach($aArray as $key) // loop through the hierarchy to get the fields names
{
eval('$exist = array_key_exists(\'' . $row[$key] .
'\', $output' . $newKey . ');');
if (!$exist)
{
$newKey .= "['" . $row[$key] . "']";
eval('$output' . $newKey . '=array();');
}
}
eval('$output' . $newKey . '[]=$row;');
}
echo(var_export($output, true));
If you wanted to use the VALUES of the fields specified in the hierarchy you can:
$output=array();
foreach($aRows as $row)
{
reset($aArray);
$eval='$output';
foreach($aArray as $key) // loop through the hierarchy to get the fields names
{
if(is_numeric($row[$key]))
{
$eval.='['.$row[$key].']'; // build the key based on the number $row value of each field named
}
else
{
$eval.='[\''.$row[$key].'\']'; // build the key based on the string $row value
}
unset($row[$key]); // remove the field from the $row
}
$eval.='=$row;';
eval($eval); // evaluate the built up index and set it to the remaining data
}
I have the following array:
$var_array = array(
"length" => 5,
"breadth" => 5,
"color" => "blue",
"size" => "medium",
"shape" => "square");
How do I extract selected variables out of the array by specifying the keys?
Example if I specify breadth and size, I get:
$breadth = 5;
$size = "medium";
$var_array = array(
"length" => 5,
"color" => "blue",
"shape" => "square");
array_diff_key and array_intersect_key:
$array = array(
'breadth' => 1,
'size' => 2,
'length' => 3,
'colour' => 4,
'shape' => 5
);
$keys = array('breadth', 'size');
$new_array = array_intersect_key($array, array_flip($keys));
$array = array_diff_key($array, $new_array);
Will produce:
// $new_array
array(2) {
["breadth"] => int(1)
["size"] => int(2)
}
// $array
array(3) {
["length"] => int(3)
["colour"] => int(4)
["shape"] => int(5)
}
If you want to put them into local variables you can do:
list($length, $colour, $shape) = array_values($new_array);
Or a less clear version:
extract($new_array);
Solution:
$keys = array('breadth', 'size'); // which keys do you want to extract?
foreach($keys as $key) {
$newArr[$key] = $var_array[$key]; // put'em in newArr
unset($var_array[$key]);
}
extract($newArr); // extract them to convert keys to variables
unset($newArr); // unset newArr
goldenparrot has already provided a good answer, but in case you want a solution that doesn't use foreach, you could use array_intersect_key instead:
$var_array = array(...)
$keysToExtract = array('breadth', 'size');
extract(array_intersect_key($var_array, array_fill_keys($keysToExtract, true));
Try this
$var_array = array(
"length" => 5,
"breadth" => 5,
"color" => "blue",
"size" => "medium",
"shape" => "square");
reset($var_array);
$myarray =array();
while (list($key, $val) = each($var_array))
{
if($key!='length' && $key!='size' )
{
$myarray[$key] = $val;
}else{
echo "$key => $val<br />";
}
}
output
size=> medium
breadth => 5
Array
(
[color] => blue
[length] => 5
[shape] => square
)
$arr = array(
'a1'=>'1',
'a2'=>'2'
);
I need to move the a2 to the top, as well as keep the a2 as a key how would I go on about it I can't seem to think a way without messing something up :)
Here is a solution which works correctly both with numeric and string keys:
function move_to_top(&$array, $key) {
$temp = array($key => $array[$key]);
unset($array[$key]);
$array = $temp + $array;
}
It works because arrays in PHP are ordered maps.
Btw, to move an item to bottom use:
function move_to_bottom(&$array, $key) {
$value = $array[$key];
unset($array[$key]);
$array[$key] = $value;
}
You can achieve that this way:
$arr = array(
'a1'=>'1',
'a2'=>'2'
);
end($arr);
$last_key = key($arr);
$last_value = array_pop($arr);
$arr = array_merge(array($last_key => $last_value), $arr);
/*
print_r($arr);
will output (this is tested):
Array ( [a2] => 2 [a1] => 1 )
*/
try this:
$key = 'a3';
$arr = [
'a1' => '1',
'a2' => '2',
'a3' => '3',
'a4' => '4',
'a5' => '5',
'a6' => '6'
];
if (isset($arr[ $key ]))
$arr = [ $key => $arr[ $key ] ] + $arr;
result:
array(
'a3' => '3',
'a1' => '1',
'a2' => '2',
'a4' => '4',
'a5' => '5',
'a6' => '6'
)
Here's a simple one liner to get this done with array_splice() and the union operator:
$arr = array('a1'=>'1', 'a2'=>'2', 'a3' => '3');
$arr = array_splice($arr,array_search('a2',array_keys($arr)),1) + $arr;
Edit:
In retrospect I'm not sure why I wouldn't just do this:
$arr = array('a2' => $arr['a2']) + $arr;
Cleaner, easier and probably faster.
You can also look at array_multisort This lets you use one array to sort another. This could, for example, allow you to externalize a hard-coded ordering of values into a config file.
<?php
$ar1 = array(10, 100, 100, 0);
$ar2 = array(1, 3, 2, 4);
array_multisort($ar1, $ar2);
var_dump($ar1);
var_dump($ar2);
?>
In this example, after sorting, the first array will contain 0, 10, 100, 100. The second array will contain 4, 1, 2, 3. The entries in the second array corresponding to the identical entries in the first array (100 and 100) were sorted as well.
Outputs:
array(4) {
[0]=> int(0)
[1]=> int(10)
[2]=> int(100)
[3]=> int(100)
}
array(4) {
[0]=> int(4)
[1]=> int(1)
[2]=> int(2)
[3]=> int(3)
}
I have this issue with multidimensional arrays.
Given the following multidimensional array:
Array(
[0] => Array("a", "b", "c")
[1] => Array("x", "y", "z")
[2] => Array("a", "b", "c")
[3] => Array("a", "b", "c")
[4] => Array("a", "x", "z")
)
I want to check its values and find duplicates (i.e. keys 0, 2 and 3) leaving just one key - value pair deleting the others, resulting in somthing like this:
Array(
[0] => Array("a", "b", "c")
[1] => Array("x", "y", "z")
[2] => Array("a", "x", "z")
)
How can I do that??
This will remove duplicate items from your array using array_unique():
$new_arr = array_unique($arr, SORT_REGULAR);
You can simply do it using in_array()
$data = Array(
0 => Array("a", "b", "c"),
1 => Array("x", "y", "z"),
2 => Array("a", "b", "c"),
3 => Array("a", "b", "c"),
4 => Array("a", "x", "z"),
);
$final = array();
foreach ($data as $array) {
if(!in_array($array, $final)){
$final[] = $array;
}
}
which will get you something like
array(3) {
[0] => array(3) {
[0] => string(1) "a"
[1] => string(1) "b"
[2] => string(1) "c"
}
[1] => array(3) {
[0] => string(1) "x"
[1] => string(1) "y"
[2] => string(1) "z"
}
[2] => array(3) {
[0] => string(1) "a"
[1] => string(1) "x"
[2] => string(1) "z"
}
}
You can go smart with serialization for comparison of arrays.
var_dump(makeUnique($data));
function makeUnique(array $data)
{
$serialized = array_map(create_function('$a', 'return serialize($a);'), $data);
$unique = array_unique($serialized);
return array_intersect_key($unique, $data);
}
Have fun
$arr = ...;
$final = array();
sort($arr);
foreach ($arr as $el) {
if (!isset($prev) || $el !== $prev)
$final[] = $el
$prev = $el;
}
This is a more efficient1 solution (log n + n instead of quadratic) but it relies on a total order between all the elements of the array, which you may not have (e.g. if the inner arrays have objects).
1 More efficient than using in_array. Turns out array_unique actually uses this algorithm, so it has the same shortcomings.
To check using array_unique on multidimensional arrays, you need to flatten it out like so, using implode.
$c=count($array)
for($i=0;$i<$c;$i++)
{
$flattened=implode("~",$array[$i]);
$newarray[$i]=$flattened;
}
if(count(array_unique($newarray)
<count($newarray))
{
//returns true if $array contains duplicates
//can also use array_unique on $newarray
//to remove duplicates, then explode,
//to return to default state
}
Hope this is helpful, took sometime to get it.
**This is example array**
$multi_com=[
[
{
"combination_id": "19"
},
{
"combination_id": "20"
},
{
"combination_id": "21"
}
],
[
{
"combination_id": "18"
},
{
"combination_id": "20"
},
{
"combination_id": "22"
}
],
[
{
"combination_id": "20"
},
{
"combination_id": "21"
}
]
]
**This is sample code**
$array1 = [];
$array2 = [];
$status = false;
foreach ($multi_com as $key => $val) {
foreach ($val as $key2 => $val2) {
if (count($array1) !== 0) {
$array_res = in_array($val2->combination_id, $array1);
if ($array_res) {
$array2[] = $val2->combination_id;
}
}
}
if (!$status) {
for ($x = 0; $x < count($val); $x++) {
$array1[] = $val[$x]->combination_id;
}
} else {
$array1 = [];
$array1 = $array2;
$array2 = [];
}
$status = true;
}
return $array1;