How to find matching values in multidimentional arrays in PHP - php

I am wondering if anyone could possibly help?....I am trying to find the matching values in two multidimensional arrays (if any) and also return a boolean if matches exist or not. I got this working with 1D arrays, but I keep getting an array to string conversion error for $result = array_intersect($array1, $array2); and echo "$result [0]"; when I try it with 2d arrays.
// matching values in two 2d arrays?
$array1 = array (array ('A8'), array (9,6,3,4));
$array2 = array (array ('A14'), array (9, 6, 7,8));
$result = array_intersect($array1, $array2);
if ($result){
$match = true;
echo "$result [0]";
}
else{
$match = false;
}
if ($match === true){
//Do something
}
else {
//do something else
}

The PHP documentation for array_intersect states:
Note: Two elements are considered equal if and only if (string) $elem1 === (string) $elem2. In words: when the string representation is the same.
So, the array to string conversion notice is occurring when PHP attempts to compare the array elements. In spite of the notice, PHP will actually convert each of the sub-arrays to a string. It is the string "Array". This means that because
array_intersect() returns an array containing all the values of array1 that are present in all the arguments.
you will end up with a $result containing every element in $array1, and a lot of notices.
How to fix this depends on exactly where/how you want to find matches.
If you just want to match any value anywhere in either of the arrays, you can just flatten them both into 1D arrays, and compare those with array_intersect.
array_walk_recursive($array1, function ($val) use (&$flat1) {
$flat1[] = $val;
});
array_walk_recursive($array2, function ($val) use (&$flat2) {
$flat2[] = $val;
});
$result = array_intersect($flat1, $flat2);
If the location of the matches in the arrays is important, the comparison will obviously need be more complex.

This error(PHP error: Array to string conversion) was caused by array_intersect($array1, $array2), cause this function will compare every single element of the two arrays.
In your situation, it will consider the comparison as this: (string)array ('A8') == (string)array ('A14'). But there isn't toString() method in array, so it will incur the error.
So, if you want to find the matching values in two multidimensional arrays, you must define your own function to find it.

Related

how to make array like this

I have an array in the array, and I want to make it just one array, and I can easily retrieve that data
i have some like
this
but the coding only combines the last value in the first array, not all values
is it possible to make it like that?
so that I can take arrays easily
I would make use of the unpacking operator ..., combined with array_merge:
$array['test2'] = array_merge(...array_merge(...$array['test2']));
In your case you need to flatten exactly twice, if you try to do it one time too much it will fail due to the items being actual arrays themselves (from PHP's perspective).
Demo: https://3v4l.org/npnTi
Use array_merge (doc) and ... (which break array to separate arrays):
function flatten($arr) {
return array_merge(...$arr);
}
$arr = [[["AAA", "BBB"]], [["CCC"]]];
$arr = flatten(flatten($arr)); // using twice as you have double depth
In your case, $arr is $obj["test2"]. If your object is json cast it to array first and if it is a string use json_decode
Live example: 3v4l
if you have a array then you can use the below code
if(!empty($array['test2'])){
$newarray = array();
foreach ($array['test2'] as $arrayRow) {
$newarray = array_merge($newarray,$arrayRow);
}
$array['test2'] = $newarray;
}

Safety net for array_slice

I read that array_merge will return NULL if you try to merge an empty array and any other array. That's not what I hope to do. I am trying to merge an array with a new array that is actually a slice of another array. ($i is an integer).
$forgotten = array_slice($matches, $i) ;
$leftOvers = array_merge($leftOvers, $forgotten);
The question is, what does array_slice return when the index is not found? If it can return null, should I do something like this:
$forgotten = array_slice($matches, $i) || array();
Also, is there any difference between using array_merge like this, and pushing $forgotten into leftOvers?
if you use array_merge over an empty array and another array it will return an array composed with the elements of the not empty array. If you try to merge two empty arrays it will return an empty array.
array_slice($matches, $i)
array_slice returns an array with all the elements of $matches with index greater or equal $i, if there are no such elements it will return an empty array.
Using array_push:
array_push($leftOvers, $forgotten)
$result will enqueue an array as a value the end of $leftOvers.
Always try to read the php man when you use a new php function, also you could get all these answers just trying to execute the functions in a test.php file.

Issue comparing two exploded php arrays to find overlap

I'm comparing the results of two exploded strings (results from a query), though when I use array_intersect to find the overlap of the arrays, I unfortunately only receive the overlap of those tags which are come first in each array...so for example if two arrays look like this:
Array1:
array(
[0]=> tag_a
[1]=> tag_b
)
Array2:
array(
[0]=> tag_a
[1]=> tag_b
)
Array_Intersect is only returning tag_a as a match. I expected the behavior of array_intersect to return tag_a as well as tab_b.
As you can see later in my code, I'm then using the matches (tags present in both arrays) to build the array contactarray. I'm able to build the array OK, it just doesn't contain the values I would have expected (ex: tag_b).
EDIT I've run several tests printing the contactarray and have applied various tag strings to those contacts and only the contacts who have have tag_a first (in the array) are being returned even though several other contacts have tag_a, though it's just not first in the array.
Thoughts?
if ($frequency == 'Weekly')
{
$data['query_tag'] = $this->db->get('tags');
foreach ($data['query_tag']->result() as $row2)
{
$contact_tags = $row2->tags;
$contact_tags_exploded = explode(",", $contact_tags);
$rule_tags_exploded = explode(",", $rule_tags);
$result = array_intersect($rule_tags_exploded, $contact_tags_exploded);
if(isset($result) && count($result) != 0){
$contactarray[] = $row2->contact_name;
}
}
}
Try array_uintersect()
Here $arr1 is your 1st array and $arr2 is second array
$intersect = array_uintersect($arr1, $arr2, 'compareDeepValue');
print_r($intersect);
function compareDeepValue($val1, $val2)
{
return strcmp($val1['value'], $val2['value']);
}
This should give you both the values
Not Sure where is the problem you are facing copy paste this code and you will see the two values properly.
$arr = array( 'tag_a','tab_b ');
$arr = array('tag_a','tab_b ');
print_r(array_intersect($arr, $arr));
use master array for first argument and array to compare as second argument.
I am not sure what problem you have.

Search Multiple Arrays for

I have officially hit a wall and I cannot figure out the solution to this issue. Any help would be much appreciated! I have tried array_intersect() but it just keeps running against the first array in the function, that wont work.
I have an infinite amounts of arrays (I'll show 4 for demonstration purposes), for example:
// 1.
array(1,2,3,4,5);
// 2.
array(1,3,5);
// 3.
array(1,3,4,5);
// 4.
array(1,3,5,6,7,8,9);
I need to figure out how to search all the arrays and find only the numbers that exist in all 4 arrays. In this example I need to only pull out the values from the arrays - 1, 3 & 5.
PS: In all reality, it would be best if the function could search against a multi dimensional array and extract only the numbers that match in all the arrays within the array.
Thanks so much for your help!
Fun question! This worked:
function arrayCommonFind($multiArray) {
$result = $multiArray[0];
$count = count($multiArray);
for($i=1; $i<$count; $i++) {
foreach($result as $key => $val) {
if (!in_array($val, $multiArray[$i])) {
unset($result[$key]);
}
}
}
return $result;
}
Note that you can just use $multiArray[0] (or any sub-array) as a baseline and check all the others against that since any values that will be in the final result must necessarily be in all individual subarrays.
How about this?
Find the numbers that exist in both array 1 and 2. Then compare those results with array 3 to find the common numbers again. Keep going as long as you want.
Is this what you are getting at?
If it's in a multidimensional array you could
$multiDimensional = array(/* Your arrays*/);
$found = array_pop($multiDimensional);
foreach($multiDimensional as $subArray)
{
foreach($found as $key=>$element)
{
if(!in_array($element, $subArray)
{
unset($found[$key]);
}
}
}
Per your comment on my other question here is a better solution:
<?php
// 1. merge the arrays
$merged_arrays = array_merge( $arr1, $arr2, $arr3, $arr4, ...);
// 2. count the values
$merged_count = array_count_values( $merged_arrays );
// 3. sort the result for elements that only matched once
for( $merged_count as $key => $value ){
if ($value == 1) {
// 4. unset the values that didn't intersect
unset($merged_count($key));
}
}
// 5. print the resulting array
print_r( $merged_count );
Performing iterated in_array() calls followed by unset() is excessive handling and it overlooks the magic of array_intersect() which really should be the hero of any solid solution for this case.
Here is a lean iterative function:
Code: (Demo)
function array_intersect_multi($arrays){ // iterative method
while(sizeof($arrays)>1){
$arrays[1]=array_intersect($arrays[0],$arrays[1]); // find common values from first and second subarray, store as (overwrite) second subarray
array_shift($arrays); // discard first subarray (reindex $arrays)
}
return implode(', ',$arrays[0]);
}
echo array_intersect_multi([[1,2,3,4,5],[1,3,5],[1,3,4,5],[1,3,5,6,7,8,9]]);
// output: 1, 3, 5
This assumes you will package the individual arrays into an indexed array of arrays.
I also considered a recursive function, but recursion is slower and uses more memory.
function array_intersect_multi($arrays){ // recursive method
if(sizeof($arrays)>1){
$arrays[1]=array_intersect($arrays[0],$arrays[1]); // find common values from first and second subarray, store as (overwrite) second subarray
array_shift($arrays); // discard first subarray (reindex $arrays)
return array_intersect_multi($arrays); // recurse
}
return implode(', ',$arrays[0]);
}
Furthermore, if you are happy to flatten your arrays into one with array_merge() and declare the number of individual arrays being processed, you can use this:
(fastest method)
Code: (Demo)
function flattened_array_intersect($array,$total_arrays){
return implode(', ',array_keys(array_intersect(array_count_values($array),[$total_arrays])));
}
echo flattened_array_intersect(array_merge([1,2,3,4,5],[1,3,5],[1,3,4,5],[1,3,5,6,7,8,9]),4);
or replace array_intersect() with array_filter() (slightly slower and more verbose):
function flattened_array_intersect($array,$total_arrays){
return implode(', ',array_keys(array_filter(array_count_values($array),function($v)use($total_arrays){return $v==$total_arrays;})));
}
echo flattened_array_intersect(array_merge([1,2,3,4,5],[1,3,5],[1,3,4,5],[1,3,5,6,7,8,9]),4);

Knowing keys type of array?

is there a command to know if an array has their keys as string or plain int?
Like:
$array1 = array('value1','value2','value3');
checkArr($array1); //> Returns true because there aren't keys as string
And:
$array2 = array('key1'=>'value1','key2'=>'value2','value3');
checkArr($array2); //> Returns false because there are keys as string
Note: I know I can parse all the array to check it.
The "compact" version to test this is:
$allnumeric =
array_sum(array_map("is_numeric", array_keys($array))) == count($array);
#Gumbo's suggestion is 1 letter shorter and could very well be a bit speedier for huge arrays:
count(array_filter(array_keys($array), "is_numeric")) == count($array);
You can use array_keys to obtain the keys for the array and then analyse the resultant array.
look at array_keys() if values are int - you got ints if strings -> strings
If you want to check the array's keys, it would be probably better to use something like this:
reset($array);
while (($key = key($array)) !== null) {
// check the key, for example:
if (is_string($key)) {
// ...
}
next($array);
}
This will be most performant, as there are no extraneous copies made of variables that you are not going to use.
On the other hand, this way is probably the most readable and makes the intent crystal clear:
$keys = array_keys($array);
foreach($keys as $key) {
// check the key, for example:
if (is_string($key)) {
// ...
}
}
Take your pick.
Important note:
Last time I checked, PHP would not let you have keys which are string representations of integers. For example:
$array = array();
$array["5"] = "foo";
echo $array[5]; // You might think this will not work, but it will
So keep that in mind when you are checking what the types of such keys are: they might have been created as strings, but PHP will have converted them to integers behind the scenes.

Categories