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.
Related
I am working with PHP,I have array and i want to change position of array, i want to display matching value in first position,For example i have following array
$cars=('Toyota','Volvo','BMW');
And i have variable $car="BMW" And i want to match this variable with array and if match then this array value should be at first in array
so expected result is (matching record at first position)
$cars=('BMW','Volvo','Toyota');
How can i do this ?
You can use array_search and array_replace for this purpose. try below mentioned code
$cars=array(0 =>'Toyota',1 =>'Volvo',2 =>'BMW');
$car="BMW";
$resultIndex = array_search($car, $cars); //get index
if($resultIndex)
{
$replacement = array(0 =>$car,array_search($car, $cars)=>$cars[0]); //swap with 0 index
$cars = array_replace($cars, $replacement); //replace
}
print_r($cars);
This can be solved in one line with array_merge and array_unique array functions.
$cars=['Toyota','Volvo','BMW'];
$car="BMW";
$cars2 = array_unique(array_merge([$car],$cars));
//$cars2: array(3) { [0]=> string(3) "BMW" [1]=> string(6) "Toyota" [2]=> string(5) "Volvo" }
$car is always at the beginning of the new array due to array_merge. If $car already exists in the $cars array, array_unique will remove it. If $car is not present in the $cars array, it is added at the beginning. If this behavior is not desired, you can use in_array to test whether $car is also contained in the $cars array.
The simplest is to "sort" by "Value = BMW", "Value != BMW".
The function that sorts and resets the keys (i.e. starts the resulting array from 0, which you want) is usort (https://www.php.net/manual/en/function.usort.php)
So your comparison function will be If ($a == "BMW") return 1, elseif ($b == "BMW") return -1, else return 0; (Paraphrased, don't expect that to work exactly - need to leave a bit for you to do!)
I have this code to get 3 random values from my array:
$maps_clean = array_filter($find_league_maps);
$random_maps = array_rand($maps_clean,3);
$league_match_maps = ",".$maps_clean[1].",".$maps_clean[2].",".$maps_clean[3].",";
This works as long as the array has at least 3 values. Now I want to modify my code so that when I want more random values than I have in my array, it just gets new ones out of the array again. Yes, this means I can have some values more than once.
How would I do that?
You can use a simple while loop and shuffle() the array inside of it, then get as many random elements as you need with array_slice(). Now if you want more random values than you have array elements, it simple takes the entire array, goes into the next iteration and takes the rest which it needs from the new shuffled array.
Code
<?php
$arr = [1,2,3,4];
$random = 5;
$result = [];
while(count($result) != $random){
shuffle($arr);
$result = array_merge($result, array_slice($arr, 0, $random - count($result)));
}
print_r($result);
?>
You can replace the elements having the same keys of an array fill with values with your $maps_clean.
$maps_clean = array_replace(array_fill(1, 3, null), array_filter($find_league_maps));
Here array_fill returns:
array(3) {
[1]=>
NULL
[2]=>
NULL
[3]=>
NULL
}
and its elements are replaced by the elements returned by array_filter($find_league_maps) that have the same keys.
The array key is start from 0 by default so, try with
$league_match_maps = ",".$maps_clean[0].",".$maps_clean[1].",".$maps_clean[2].",";
also what is the output of count($maps_clean)?
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.
This question already has answers here:
How to check if PHP array is associative or sequential?
(60 answers)
Closed last year.
I'd like to be able to pass an array to a function and have the function behave differently depending on whether it's a "list" style array or a "hash" style array. E.g.:
myfunc(array("One", "Two", "Three")); // works
myfunc(array(1=>"One", 2=>"Two", 3=>"Three")); also works, but understands it's a hash
Might output something like:
One, Two, Three
1=One, 2=Two, 3=Three
ie: the function does something differently when it "detects" it's being passed a hash rather than an array. Can you tell I'm coming from a Perl background where %hashes are different references from #arrays?
I believe my example is significant because we can't just test to see whether the key is numeric, because you could very well be using numeric keys in your hash.
I'm specifically looking to avoid having to use the messier construct of myfunc(array(array(1=>"One"), array(2=>"Two"), array(3=>"Three")))
Pulled right out of the kohana framework.
public static function is_assoc(array $array)
{
// Keys of the array
$keys = array_keys($array);
// If the array keys of the keys match the keys, then the array must
// not be associative (e.g. the keys array looked like {0:0, 1:1...}).
return array_keys($keys) !== $keys;
}
This benchmark gives 3 methods.
Here's a summary, sorted from fastest to slowest. For more informations, read the complete benchmark here.
1. Using array_values()
function($array) {
return (array_values($array) !== $array);
}
2. Using array_keys()
function($array){
$array = array_keys($array); return ($array !== array_keys($array));
}
3. Using array_filter()
function($array){
return count(array_filter(array_keys($array), 'is_string')) > 0;
}
PHP treats all arrays as hashes, technically, so there is not an exact way to do this. Your best bet would be the following I believe:
if (array_keys($array) === range(0, count($array) - 1)) {
//it is a hash
}
No, PHP does not differentiate arrays where the keys are numeric strings from the arrays where the keys are integers in cases like the following:
$a = array("0"=>'a', "1"=>'b', "2"=>'c');
$b = array(0=>'a', 1=>'b', 2=>'c');
var_dump(array_keys($a), array_keys($b));
It outputs:
array(3) {
[0]=> int(0) [1]=> int(1) [2]=> int(2)
}
array(3) {
[0]=> int(0) [1]=> int(1) [2]=> int(2)
}
(above formatted for readability)
My solution is to get keys of an array like below and check that if the key is not integer:
private function is_hash($array) {
foreach($array as $key => $value) {
return ! is_int($key);
}
return false;
}
It is wrong to get array_keys of a hash array like below:
array_keys(array(
"abc" => "gfb",
"bdc" => "dbc"
)
);
will output:
array(
0 => "abc",
1 => "bdc"
)
So, it is not a good idea to compare it with a range of numbers as mentioned in top rated answer. It will always say that it is a hash array if you try to compare keys with a range.
Being a little frustrated, trying to write a function to address all combinations, an idea clicked in my mind: parse json_encode result.
When a json string contains a curly brace, then it must contain an object!
Of course, after reading the solutions here, mine is a bit funny...
Anyway, I want to share it with the community, just to present an attempt to solve the problem from another prospective (more "visual").
function isAssociative(array $arr): bool
{
// consider empty, and [0, 1, 2, ...] sequential
if(empty($arr) || array_is_list($arr)) {
return false;
}
// first scenario:
// [ 1 => [*any*] ]
// [ 'a' => [*any*] ]
foreach ($arr as $key => $value) {
if(is_array($value)) {
return true;
}
}
// second scenario: read the json string
$jsonNest = json_encode($arr, JSON_THROW_ON_ERROR);
return str_contains($jsonNest, '{'); // {} assoc, [] sequential
}
NOTES
php#8.1 is required, check out the gist on github containing the unit test of this method + Polyfills (php>=7.3).
I've tested also Hussard's posted solutions, A & B are passing all tests, C fails to recognize: {"1":0,"2":1}.
BENCHMARKS
Here json parsing is ~200 ms behind B, but still 1.7 seconds faster than solution C!
What do you think about this version? Improvements are welcome!
I know there is array_unique function, but I want to remove duplicates. Is there a built-in function or do I have to roll my own.
Example input:
banna, banna, mango, mango, apple
Expected output:
apple
You can use a combination of array_unique, array_diff_assoc and array_diff:
array_diff($arr, array_diff_assoc($arr, array_unique($arr)))
You can use
$singleOccurences = array_keys(
array_filter(
array_count_values(
array('banana', 'mango', 'banana', 'mango', 'apple' )
),
function($val) {
return $val === 1;
}
)
)
See
array_count_values — Counts all the values of an array
array_filter — Filters elements of an array using a callback function
array_keys — Return all the keys or a subset of the keys of an array
callbacks
Just write your own simple foreach loop:
$used = array();
$array = array("banna","banna","mango","mango","apple");
foreach($array as $arrayKey => $arrayValue){
if(isset($used[$arrayValue])){
unset($array[$used[$arrayValue]]);
unset($array[$arrayKey]);
}
$used[$arrayValue] = $arrayKey;
}
var_dump($array); // array(1) { [4]=> string(5) "apple" }
have fun :)
If you want to only leave values in the array that are already unique, rather than select one unique instance of each value, you will indeed have to roll your own. Built in functionality is just there to sanitise value sets, rather than filter.
You want to remove any entries that have duplicates, so that you're left with only the entries that were unique in the list?
Hmm it does sound like something you'll need to roll your own.
There is no existing function; You'll have to do this in two passes, one to count the unique values and one to extract the unique values:
$count = array();
foreach ($values as $value) {
if (array_key_exists($value, $count))
++$count[$value];
else
$count[$value] = 1;
}
$unique = array();
foreach ($count as $value => $count) {
if ($count == 1)
$unique[] = $value;
}
The answer on top looks great, but on a side note: if you ever want to eliminate duplicates but leave the first one, using array_flip twice would be a pretty simple way to do so. array_flip(array_flip(x))
Only partially relevant to this specific question - but I created this function from Gumbo's answer for multi dimensional arrays:
function get_default($array)
{
$default = array_column($array, 'default', 'id');
$array = array_diff($default, array_diff_assoc($default, array_unique($default)));
return key($array);
}
In this example, I had cached statuses and each one other than the default was 0 (the default was 1). I index the default array from the IDs, and then turn it into a string. So to be clear - the returned result of this is the ID of the default status providing it's in the same part of the multi dimensional array and not the key of it
PHP.net http://php.net/manual/en/function.array-unique.php
array array_unique ( array $array [, int $sort_flags = SORT_STRING ] )
Takes an input array and returns a new array without duplicate values.
New solution:
function remove_dupes(array $array){
$ret_array = array();
foreach($array as $key => $val){
if(count(array_keys($val) > 1){
continue;
} else {
$ret_array[$key] = $val;
}
}