PHP - Get the keys of values which are congruent in an array - php

I have an array which potentially is able to carry multiple congruent values.
$a = array( "0" => "red", "1" => "green" , "2" => "red" , "3" => "blue", "4" => "blue", "5" => "blue" );
Now, I need to know the keys of all elements which have at least one congruent value.
My prefered result would be an array which has subarrays- and in each subarray the keys of the different congruent values get stored. So that I know which one of the keys of array $a have the same value.
$b = array(array("0" => "0", "1" => "2"), array("0" => "3", "1" => "4", "2" => "5"));
What is the most efficient way to do that?
Thank you

You can use array_count_values() to get the frequency count for each color. Then iterate over the array $a and check each color's frequency count. If it's greater than 1, add it to the result at the appropriate color index in $keys.
<?php
$a = array( "0" => "red", "1" => "green" , "2" => "red" , "3" => "blue", "4" => "blue", "5" => "blue" );
$group_by_data = array_count_values($a);
$keys = [];
foreach($a as $key => $color){
if($group_by_data[$color] > 1){
if(!isset($keys[$color])) $keys[$color] = [];
$keys[$color][] = $key;
}
}
print_r($keys);
Demo: https://3v4l.org/mI02u

Use array_unique to find all unique values then loop through it and use array_keys to find all the keys of each element.
$a = array( "0" => "red", "1" => "green" , "2" => "red" , "3" => "blue", "4" => "blue", "5" => "blue" );
$unique=array_unique($a);
$result=array();
foreach($unique as $value){
$allkeys=array_keys($a, $value);
if(count($allkeys)>1)
$result[]=$allkeys;
}
print_r($result);

Just to have a play with performance, I tried using a (sort of) combination of the two approaches. First count the values, then loop over this and use array_keys() to get the entries with these colors...
$a = array( "0" => "red", "1" => "green" , "2" => "red" , "3" => "blue", "4" => "blue", "5" => "blue" );
$group_by_data = array_count_values($a);
$keys = [];
foreach ( $group_by_data as $key => $value ) {
if ( $value > 1 ) {
$keys[$key] = array_keys($a, $key);
}
}
print_r($keys);

Related

How to get the key in an array when the value is known and the keys are strings of numbers?

There seems to be a bug with array_search, how do I work around it?
$arr = [
"0" => "Zero",
"1" => "One",
"2" => "Two",
];
$val = array_search("Zero", $arr, true);
echo gettype($val); // returns integer instead of string
echo $val;
I want to get "0" instead of 0. How do I go about doing that?
You can typecast if needs a string result:
$arr = [
"0" => "Zero",
"1" => "One",
"2" => "Two",
];
$val = (string) array_search("Zero", $arr, true);// You can typecast to String here
echo gettype($val); // this will return string now
echo $val;

Get current index in array_walk function

$A = ["0" => "a", "1" => "b", "2" => "c"];
$B = ["0" => "aa", "1" => "bb", "2" => "cc"]
array_walk($A,function($item) use($B){
$temp[] = $item;
$temp[] = $B[?];
});
how to fill the ? above? how to get the current index in array_walk?
If I understood correctly something like that would work
$A = ["0" => "a", "1" => "b", "2" => "c"];
$B = ["0" => "aa", "1" => "bb", "2" => "cc"]
array_walk($A,function($item, $key) use($B){
$temp[] = $item;
$temp[] = $B[$key];
});

PHP diff array value and not key diff

I have a problem and I hope, I can be helped to fix this problem.
My problem is I got this two arrays
$array1 = ["test1" => "red", "test2" => "blue", "test3" => "green"];
$array2 = ["test1" => "red", "test2" => "blue", "test3" => "blue"];
as you can see the difference is the array key test3's value there are a diff, my problem is i need to know the key test3 have a diff and from $array1 to $array2
I have tried array_diff and array_intersect but its not what I want.
I have a product and i need to know what there are changes from last run, and if i use on of this to command its not telling my where the diff are but what the diff is.
Can somebody help here and explain what i can do or about there are a function to handle this problem?
<?php
$array1 = ["test1" => "red", "test2" => "blue", "test3" => "green"];
$array2 = ["test1" => "red", "test2" => "blue", "test3" => "blue"];
$result=array_diff($array1,$array2);
print_r($result);
?>
This shud work
o/p : Array ( [test3] => green )
<?php
$array1 = array("a" => "green", "b" => "brown", "c" => "blue", "d" => "red");
$array2 = array("a" => "green", "b" => "brown", "c" => "blue", "d" => "yellow");
$result = array_diff_assoc($array1, $array2);
echo print_r($result, true);
?>

comparing two arrays in php

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'));
?>

How to build a hierarchical associative array out of two other arrays like "group by"

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
}

Categories