Comparing values of a multi-dimensional array - php

$data = [];
$data['set1'] = ['label1'=>'001', 'label2'=>'002'];
$data['set2'] = ['label1'=>'003', 'label2'=>'004'];
$data['set3'] = ['label1'=>'001', 'label2'=>'006'];
$data['set4'] = ['label1'=>'001', 'label2'=>'002'];
I'd like to check if value of labelx in any setx is identical. All I can think of is run foreach loops to compare one set with the rest, one at a time.
Is there any elegant solution that checks for similar values in ALL sets without doing the loops manually?

array_column() and array_count_values() will do the trick.
First get the column values as array using array_column and then find identical values in an array using array_count_values.
Like this:
<?php
$data = [];
$data['set1'] = ['label1'=>'001', 'label2'=>'002'];
$data['set2'] = ['label1'=>'003', 'label2'=>'004'];
$data['set3'] = ['label1'=>'001', 'label2'=>'006'];
$data['set4'] = ['label1'=>'001', 'label2'=>'002'];
$label1_values=array_column($data,'label1');
$label2_values=array_column($data,'label2');
print_r(array_count_values($label1_values));
print_r(array_count_values($label2_values));
?>
Output:
Array
(
[001] => 3
[003] => 1
)
Array
(
[002] => 2
[004] => 1
[006] => 1
)

Related

Combine dynamic arrays with dynamic keys in to single arrays

I have this dynamic multiple arrays that I need to combine in one array and serialized them. The problem is I need to keep both key and value.
$arr = array($bet_option_id => $bet_option_name);
Here i need to keep both bet_option_id AND bet_option_name. Then this result output:
Array ( [997650802] => Over 2.5 )
Array ( [997650807] => Yes )
This need to be simply
Array
(
[997650802] => Over 2.5
[997650807] => Yes
)
As it's dynamic, sometimes not comes with just single array so apparently I couldn't get it working. I need to retrieve both bet_option_id & bet_option_name. Tried something like this:
$arr = array($bet_option_id => $bet_option_name); //This is where all array keys, values are stores
$result = array();
foreach ($arr as $array) {
$result = array_merge($result, $array);
}
Any inputs will be nice.
Rather than create individual arrays like...
$arr = array($bet_option_id => $bet_option_name);
If you first create an empty array ( like you do with $result)
$arr = array();
and then add each item in using
$arr[$bet_option_id] = $bet_option_name;
Then you don't need to manipulate the array after - just create it as you want it in the first place.
You could either do like Nigel Ren suggested which is the most elegant solution
In case that you do not have arrays that their keys are entirely numeric you may use array_merge. The quote following is from PHP array-merge
Example #2 Simple array_merge() example
$array1 = array();
$array2 = array(1 => "data");
$result = array_merge($array1, $array2);
Don't forget that numeric keys will be renumbered!
Array
(
[0] => data
)
Alternatively you can always join arrays together like this
$a1 = [ 997650802 => 'Over 2.5' ];
$a2 = [ 997650807 => 'Yes' ];
var_dump( $a1 + $a2 ); // result is [997650802 => 'Over 2.5',997650807 => 'Yes']
You can check more about Array Types and Array Operators

How can I filter a multidimensional array and count the filtered values?

I have an array coming from a mysql database. So it is structured this way (just the first two entry):
Array
(
[0] => Array
(
[id_cre] => CD000000001
[0] => CD000000001
[id_az] => AZ000000001
[1] => AZ000000001
)
[1] => Array
(
[id_cre] => CD000000002
[0] => CD000000002
[id_az] =>
[1] =>
)
)
I would like to count how many entries in the array have [id_az] =>''.
If I do:
count($creds)
I get 2 (the number of items in the array).
I'd prefer to reuse this array (the query runs already for another report), instead of doing a new query with the WHERE clause to subselect WHERE id_az = ''.
Any hint(s)?
This should work for you:
Just get the column id_az with array_column() and count() the array then, e.g.
echo count(array_column($creds, "id_az"));
Why not use a good old foreach loop?
$count = 0;
foreach($data as $row)
{
$count += empty($row['id_az']) ? 0 : 1;
}
or alternativly an array_map with a anonymous function
$count = 0;
array_map(function($row) use (&$count) { $count += empty($row['id_az']) ? 0 : 1; }, $data);
But this is PHP >5.3. Callbacks won't work, since you won't have access to a variable to store your count in.

PHP Array_unique value error in while loop

This is my PHP script for getting plan
This is my table
plan
3|6
6|12
3|12
and
<?php
$tenure="SELECT plan from ".TABLE_TYBO_EMI_GATEWAY;
$t_result=dbQuery($tenure);
while($t_data=mysql_fetch_assoc($t_result))
{
$arrayVal=explode("|",$t_data['plan']);
print_r(array_unique($arrayVal));
}
?>
and I got the result is
Array ( [0] => 3 [1] => 6 ) Array ( [0] => 6 [1] => 12 )
Here I want 3,6,12 only. What is the problem in my script
before your while loop add this line:
$arrayVal = array();
and replace $arrayVal=explode("|",$t_data['plan']); with $arrayVal=array_merge($arrayVal, explode("|",$t_data['plan']));
$tenure="SELECT plan from ".TABLE_TYBO_EMI_GATEWAY;
$t_result=dbQuery($tenure);
$arrayVal = array();
while($t_data=mysql_fetch_assoc($t_result))
{
$arrayVal = array_merge($arrayVal, explode("|",$t_data['plan']));
}
print_r(array_unique($arrayVal));
Note: When using array_merge with associated arrays, it will overwrite values for same keys, but when using numeric keys array_merge will not overwrite them instead append as new values.

PHP string to nested / multidimensional array

I have this example php string:
$string = "#[item_1][door] #[mozart][grass] = yes #[mozart][green] = no #[mozart][human] #[blue][movie]=yes #[item_1][beat] = yes #[item_1][music] = no
";
now $string idented just to easy view:
#[item_1][door]
#[mozart][grass] = yes
#[mozart][green] = no
#[mozart][human]
#[blue][movie]=yes
#[item_1][beat] = yes
#[item_1][music] = no
I want to know how can i get this string ( or other string following this style ) and transform in an array that looks like:
Array
(
[item_1] => Array
(
[door] => Array
(
[mozart] => Array
(
[grass] => yes
[green] => no
[human] => Array
(
[blue] => Array
(
[movie] => yes
)
)
)
)
[beat] => yes
[music] => no
)
)
What i tried
I tried to use and recursive function to create an nested array but i can't have access to the array pointer ( in deep levels ) in recursive functions.. don't know why.. maybe is the wrong patch to the answer.
thank you,
OK, I hope you still need this, because I wasted more time than I'd like to admin getting this right :)
Basically, my approach was to first manipulate the string into the format [set][of][keys]=value, and then loop through the string of keys and comparing them with the last set of keys to create the correct key hierarchy. I used eval because it's easier, but you can write a replacement function if you can't stomach seeing that function in your code:
//FIRST WE GET THE STRING INTO EASIER TO WORK WITH CHUNKS
$original_string = "#[item_1][door] #[mozart][grass] = yes #[mozart][green] = no #[mozart][human] #[blue][movie]=yes #[item_1][beat] = yes #[item_1][music] = no ";
$cleaned_string = str_replace('] #[','][',$original_string);
/* This results in clusters of keys that equal a value:
#[item_1][door][mozart][grass] = yes #[mozart][green] = no #[mozart][human][blue][movie]=yes #[item_1][beat] = yes #[item_1][music] = no
OR (with line breaks for clarity):
#[item_1][door][mozart][grass] = yes
#[mozart][green] = no
#[mozart][human][blue][movie]=yes
#[item_1][beat] = yes
#[item_1][music] = no */
//break it up into an array:
$elements = explode('#',$cleaned_string);
//create a variable to compare the last string to
$last_keys = "";
//and another that will serve as our final array
$array_of_arrays = array();
//now loop through each [item_1][door][mozart][grass] = yes,[mozart][green] = no, etc
foreach($elements as $element){
if ($element==""){continue;} //skip the first empty item
//break the string into [0] = group of keys and [1] the value that terminates the string
//so [item_1][door][mozart][grass] = yes BECOMES [item_1][door][mozart][grass], AND yes
$pieces = explode('=',str_replace(array('[',']'),array("['","']"),trim($element)));
//now compare this set of keys to the last set of keys, and if they overlap merge them into a single key string
$clean_keys = combine_key_strings($pieces[0],$last_keys);
//set the new key string the value for the next comparison
$last_keys = $clean_keys;
//and (ugly, I know) we use an eval to convert "[item_1][door][mozart][grass]='yes'" into a properly keyed array
eval("\$array_of_arrays".$clean_keys." = '".trim($pieces[1])."';");
}
//now dump the contents
print_r($array_of_arrays);
//THIS FUNCTION COMPA
function combine_key_strings($new,$old){
//get the key that starts the newer string
$new_keys = explode('][',$new);
$first_key = $new_keys[0].']';
//see if it appears in the last string
$last_occurance = strrpos ($old,$first_key);
//if so, merge the two strings to create the full array keystring
if (is_int($last_occurance)){
return substr($old,0,$last_occurance).$new;
}
return $new;
}
This should spit out your correctly nested array:
Array
(
[item_1] => Array
(
[door] => Array
(
[mozart] => Array
(
[grass] => yes
[green] => no
[human] => Array
(
[blue] => Array
(
[movie] => yes
)
)
)
)
[beat] => yes
[music] => no
)
)
Good night!

How to compare arrays and extract the difference?

I have two arrays that I would like to compare and ultimately wind up with a single array with everything combined, having no duplicates. Can someone please tell me which function I should use? There are so many that it's a bit confusing.
$array1[]['name'] = 'Kim, Jones';
$array1[]['name'] = 'Jim, Miller';
array1 is an array I built that I want added to an array coming from the database. The key in the second array is also named "name". Thanks.
EDIT:
I managed to merge these two arrays but I can still see duplicates.
This is what the first array looks like:
Array
(
[0] => Array
(
[WNumber] => ADMIN
[Name] => Tim, Cooley
[Employer] => CalPERS
[Student] => 1
[Perm] => 1
[QA] => 0
[Supervisor] => 1
[RQW] => 0
)
My second array is built like this:
$add_names[]['Name']='Jim, Jones';
I just want to add $add_names to the first array WHERE there are no duplicates.
I'm tempted to sell you on CakePHP, since it has a number of functions that makes this easy in its "Set" class. Your problem is that you have the results in a nested array. A simple "array_unique" does not work in a nested array.
I'd do it the old fashioned way...
$array1[]['name'] = 'Kim, Jones';
$array1[]['name'] = 'Jim, Miller';
$array2[]['name'] = 'Kim, Jones';
$array2[]['name'] = 'Jimbo, Miller';
$array2[]['name'] = 'Jim, Jones';
$new_array=array_merge($array1, $array2);
$out_array = array();
$key_array = array();
foreach($new_array as $i => $row) {
if (empty($key_array[$row['name']])) {
$out_array[] = $row;
}
$key_array[$row['name']] = 1;
}
print_r($out_array);
This code works for me...
I think you'll need to use a combination of array_merge (adds the two arrays together) and array_unique (removes duplicate values).
$resulting_array = array_unique(array_merge($array1, $array2));
Note that array_unique will not work correctly when using multi-dimensional arrays, so if your array data looks the way you put it in your question, you'll have to think of a way around that. One of the comments on the array_unique page suggests serialize'ing all array values before running array_unique on it. Afterwards you'd just run unserialize on all array elements. Note that this can mean a performance hit if you have a big array, so you might want to consider avoiding multi-dimensional arrays in this scenario.
Something like this:
$merged_array = array_merge($array1, $array2);
$serialized_array = array_map("serialize", $merged_array);
$filtered_array = array_unique($serialized_array);
$final_array = array_map("unserialize", $filtered_array);
There isn't a direct function for handling what you are looking for in php, probably you need to write a function for it.
What I understood from your question is that you have 2 arrays :
$a = array( array( 'name' => 'Omid' ), 12 );
$b = array( array( 'name' => 'testing' ) );
and you want to merge them to get
$merge = array( array( 'name' => 'testing' ), 12 );
if that's what you want then you might want to take a look at this comment array merge recursive which leads to this code :
function array_merge_recursive_distinct ( array &$array1, array &$array2 )
{
$merged = $array1;
foreach ( $array2 as $key => &$value )
{
if ( is_array ( $value ) && isset ( $merged [$key] ) && is_array ( $merged [$key] ) )
{
$merged [$key] = array_merge_recursive_distinct ( $merged [$key], $value );
}
else
{
$merged [$key] = $value;
}
}
return $merged;
}
Does php's array_diff() do what you want?
http://us.php.net/manual/en/function.array-diff.php
or more likely array_diff_assoc:
http://us.php.net/manual/en/function.array-diff-assoc.php
Does array_diff work for you?
Description
array array_diff ( array $array1 , array $array2 [, array $ ... ] )
Compares array1 against array2 and returns the difference.

Categories