PHP - how to compare value of arrays in dynamic way? - php

Ok, I have following 'challange';
I have array like this:
Array
(
[0] => Array
(
[id] => 9
[status] => 0
)
[1] => Array
(
[id] => 10
[status] => 1
)
[2] => Array
(
[id] => 11
[status] => 0
)
)
What I need to do is to check if they all have same [status].
The problem is, that I can have 2 or more (dynamic) arrays inside.
How can I loop / search through them?
array_diff does support multiple arrays to compare, but how to do it? :(
Which ever loop I have tried, or my Apache / browser died - or I got completely bogus data back.

You could just put the problem apart to make it easier to solve.
First get all status items from your array:
$status = array();
forach($array as $value)
{
$status[] = $value['status'];
}
You now have an array called $status you can see if it consists of the same value always, or if it has multiple values:
$count = array_count_values($status);
echo count($count); # number of different item values.

Try this code:
$status1 = $yourArray[0]['status'];
$count = count($yourArray);
$ok = true;
for ($i=1; $i<$count; $i++)
{
if ($yourArray[$i]['status'] !== $status1)
{
$ok = false;
break;
}
}
var_dump($ok);

function allTheSameStatus( $data )
{
$prefStatus = null;
foreach( $data as $array )
{
if( $prefStatus === null )
{
$prefStatus = $array[ 'status' ];
continue;
}
if( $prefStatus != $array[ 'status' ] )
{
return false;
}
}
return true;
}

I'm not sure what you want as output but you could iterate through the outer array and create an output array that groups the inner arrays by status:
$outputArray = array();
foreach ($outerArray as $an_array) {
$outputArray[$an_array['status']][] = $an_array['id'];
}

Related

How can i compare values within a multidimensional array

I am developing a Bio-metric election system but i am facing problem regarding election results.
I got this array after executing a query.
Array
(
[paty1] => Array
(
[NA122] => stdClass Object
(
[count] => 2
)
[NA2] => stdClass Object
(
[count] => 0
)
[NA56] => stdClass Object
(
[count] => 1
)
)
[party2] => Array
(
[NA122] => stdClass Object
(
[count] => 0
)
[NA2] => stdClass Object
(
[count] => 0
)
[NA56] => stdClass Object
(
[count] => 0
)
)
)
This array is stored in $data and it can have unlimited indexes.
Now if count of [Paty1][NA122] is greater then count of [Party2][NA122] so i will declare Party1 win in NA122 and i have to compare it with n number of indexes.
e.g. there is another index pary3 so firstly I will compare count of [party1][NA122] with [party2][NA122] and then with [party3][NA122] and winner will be the one with greater count . Can you please help me??
Thanks in advance
Try this:
foreach(current($Result) as $Const=>$val){
echo "Winner of Constituency '$Const': ". findWinner($Const,$Result).PHP_EOL;
}
function findWinner($Const, $Result){
$Max = 0;
$Winner = '';
foreach($Result as $Party => $ConstList){
if($ConstList[$Const]->count>$Max){
$Max = $ConstList[$Const]->count;
$Winner = $Party;
}
}
return $Winner;
}
Check live code here:
https://www.tehplayground.com/x5sPu7JxuexOdwU8
So you want to get the party with the max count for a given NA#.
You can use a function like this:
function maxParty($data, $na) {
$max = null;
foreach($data as $party => $values) {
if(is_null($max)) {
$max = $party;
continue;
} else {
if($values[$na]->count > $data[$max][$na]->count) {
$max = $party;
}
}
}
return $max;
}
Then you feed this function with a $data array and the NA# you want to calculate the max party with. For example
$winner = maxParty($data, 'NA122');
It will return the key for the winner party. I.e. "party1"
Do you mean something like this:
<?php
$data=getData();
$maxValue;
$maxKey;
foreach($data as $key => $paty)
if(!isset($maxValue) || $paty->count>$maxValue){
$maxValue=$paty->count;
$maxKey=$key;
}
echo "$maxValue $maxKey";
function getData(){
$a=array();
for($i=1;$i<100;$i++)
$a["paty$i"]=(object) array("count"=>$i);
return $a;
}
?>
Explanation:
getData returns an array like the one you described
foreach($data as $key => $paty) - iterates through the entire array
if ( ) -- checks if the current value is greater than the previous max
If you want to know more about PHP:
foreach, objects, arrays and google

Finding duplicate values in multidimensional array

I'm trying to code a system which will find user accounts that are using the same IPs, and print out the matches with their keys. I have already coded the part where the data is pulled from MySQL and nicely put in a multidimensional associative array, so input looks like this (the key is UserID, values are IP addresses):
$users = array(
100 => array("1.1.1.1","2.2.2.2","3.3.3.3"),
200 => array("1.1.1.1","4.4.4.4","5.5.5.5"),
300 => array("1.1.1.1","4.4.4.4","7.7.7.7")
);
The expected output would be:
Array
(
[1.1.1.1] => Array
(
[0] => 100
[1] => 200
[2] => 300
)
[4.4.4.4] => Array
(
[0] => 200
[1] => 300
)
)
I have searched and used trial and error with multiple nested foreach that would loop through the arrays, tried array_intersect to find the duplicates, but nothing gets me close to the expected output. By now I think I'm overthinking the problem and the solution is really easy, but I cannot seem to get close to the expected output. Any help is appreciated, thank you.
$output = array();
// loop through each user
foreach ($users as $id => $ips) {
// loop through each IP address
foreach ($ips as $ip) {
// add IP address, if not present
if (!isset($output[$ip])) {
$output[$ip] = array();
}
// add user ID to the IP address' array
$output[$ip][] = $id;
}
}
$users = array(
100 => array("1.1.1.1","2.2.2.2","3.3.3.3"),
200 => array("1.1.1.1","4.4.4.4","5.5.5.5"),
300 => array("1.1.1.1","4.4.4.4","7.7.7.7")
);
$allIP = [];
foreach ( $users as $user ) {
$allIP = array_merge($allIP, $user);
}
$allIP = array_unique($allIP);
$result = [];
foreach ( $allIP as $ip ) {
foreach ( $users as $key => $val ) {
if ( in_array($ip, $val, true) ) {
if ( !isset($result[$ip]) ) {
$result[$ip] = [];
}
array_push($result[$ip], $key);
}
}
}
$result = array_filter($result, function ($v, $k) {
if ( count($v) > 1 ) {
return true;
} else {
return false;
}
}, ARRAY_FILTER_USE_BOTH);
var_dump($result);
Although I think it's better to do this by SQL as well. It could be extremely slow to achieve this by PHP.

How to compare 2 arrays for common items in PHP?

I am writing a script to compare the achievements of one player to another in a game. In each of the arrays the id and timestamp will match up on some entries. I have included a sample of one of the start of the 2 separate arrays:
Array
(
[0] => Array
(
[id] => 8213
[timestamp] => 1384420404000
[url] => http://www.wowhead.com/achievement=8213&who=Azramon&when=1384420404000
[name] => Friends In Places Higher Yet
)
[1] => Array
(
[id] => 6460
[timestamp] => 1384156380000
[url] => http://www.wowhead.com/achievement=6460&who=Azramon&when=1384156380000
[name] => Hydrophobia
)
I want to find all of the array items where the id and timestamp match. I have looked into array_intersect but I don't think this is what I am looking for as it will only find items when the entries are identical. Any help much appreciated.
You may use array_intersect_assoc function.
Try something like this:
<?php
$key_match = Array();
//Loop first array
foreach($array as $key => $element){
//Compare to second array
if($element == $array2[$key]){
//Store matching keys
$key_match[] = $key;
}
}
?>
$key_match will be an array with all matching keys.
(I'm at work and havn't had time to test the code)
Hope it helps
EDIT:
Fully working example below:
<?php
$a1["t"] = "123";
$a1["b"] = "124";
$a1["3"] = "125";
$a2["t"] = "123";
$a2["b"] = "124";
$a2["3"] = "115";
$key_match = Array();
//Loop first array
foreach($a1 as $key => $element){
//Compare to second array
if($element == $a2[$key]){
//Store matching keys
$key_match[] = $key;
}
}
var_dump($key_match);
?>
If you want to go on an exploration of array callback functions, take a look at array_uintersect. It's like array_intersect except you specify a function to use for the comparison. This means you can write your own.
Unfortunately, you need to implement a function that returns -1, 0 or 1 based on less than, same as, greater than, so you need more code. But I suspect that it'll be the most efficient way of doing what you're looking for.
function compareArrays( $compareArray1, $compareArray2 ) {
if ( $compareArray1['id'] == $compareArray2['id'] && $compareArray1['timestamp'] == $compareArray2['timestamp'] ) {
return 0;
}
if ( $compareArray1['id'] < $compareArray2['id'] ) {
return -1;
}
if ( $compareArray1['id'] > $compareArray2['id'] ) {
return 1;
}
if ( $compareArray1['timestamp'] < $compareArray2['timestamp'] ) {
return -1;
}
if ( $compareArray1['timestamp'] > $compareArray2['timestamp'] ) {
return 1;
}
}
var_dump( array_uintersect( $array1, $array2, "compareArrays") );

Compare a multi-dimensional array with a simple array and extract the difference

I've a $_POST that sends an array. And i've a prevoious array with contains a key that could contain or not one of the values from teh $_POST.
For Example:
$_post: Array ( [0] => 13 [1] => 10 [2] => 52)
Previous: Array ( [0] => Array ( [collection_id] => 13 [artwork_id] => 21 )
[1] => Array ( [collection_id] => 11 [artwork_id] => 21 ) )
So i need to check if the $_POST itms already exists on the previuos array ([collection_id] key) and extract the new ones (in this case [1] => 10 [2] => 52) to ve added to the database and also get those which has changed that need to be removed from the database (replaced) by the new values.
This my current code but not working well...
$new_nodes = array();
$i = 0;
foreach($old_nodes as $node){
foreach ($collections as $collection) {
$new = array('collection_id' => $collection, 'artwork_id' => $artwork['id']);
if(array_diff($node, $new)){
if($collection > 0){
array_push($new_nodes, $new);
}
}
else{
unset($old_nodes[$i]);
}
}
$i++;
}
foreach($new_nodes as $node){
for ($i = 0; $i <= count($new_nodes); $i++) {
if(isset($new_nodes[$i])){
if(!array_diff($node, $new_nodes[$i])){
unset($new_nodes[$i]);
}
}
}
}
NOTE: old_nodes is "Previous" and $collections is "$_POST"
Try something like this:
$old_nodes = array();
$new_nodes = array();
$del_nodes = array();
foreach ($collections as $collection) {
array_push($old_nodes, $collection['collection_id']);
}
$new_nodes = array_diff($collections, $old_nodes);
$del_nodes = array_diff($old_nodes, $collections);

PHP - Counting matching arrays in array

I have an array structure that looks like this:
Array
(
[0] => Array
(
[type] => image
[data] => Array
(
[id] => 1
[alias] => test
[caption] => no caption
[width] => 200
[height] => 200
)
)
[1] => Array
(
[type] => image
[data] => Array
(
[id] => 2
[alias] => test2
[caption] => hello there
[width] => 150
[height] => 150
)
)
)
My question is, how can I get a count of the number of embedded arrays that have their type set as image (or anything else for that matter)? In practise this value can vary.
So, the above array would give me an answer of 2.
Thanks
The simplest way would simply be to loop over all the child arrays and check their type, incrementing a counter if it matches the required type.
$count = 0;
foreach ( $myarray as $child ){
if ( $child['type'] == 'image' ){
$count++;
}
}
If you have PHP 5.3.0 or better you could use array_reduce (untested):
$count = array_reduce($myarray,
function($c, $a){ return $c + (int)($a['type'] == 'image'); },
0
);
Both of these could be moved into a function returning $count which would allow you to specify the type to count. For example:
function countTypes(array $haystack, $type){
$count = 0;
foreach ( $haystack as $child ){
if ( $child['type'] == $type ){
$count++;
}
}
return $count;
}
As you can see from other answers there is far more error checking you could do, however you as you haven't said what should be impossible (which you would want to use assert for).
The possible errors are:
The child is not an array
The child does have the type key set
If your array should always be set out like your example, failing silently (by putting a check in an if statement) would be a bad idea as it would mask an error in the program elsewhere.
You'll have to iterate over each element of your array and check whether element match your condition:
$data = array(...);
$count = 0;
foreach ($data as $item) {
if ('image' === $item['type']) {
$count++;
}
}
var_dump($count);
<?php
$arr = // as above
$result = array();
for ( $i = 0; $i < count( $arr ); $i++ )
{
if ( !isset( $result[ $arr[$i]['type'] ] ) )
$result[ $arr[$i]['type'] ] = 0;
$result[ $arr[$i]['type'] ]++;
}
echo $result['image']; // 2
?>
In addition to Yacoby's answer, you could do it functional-style with a closure if you're using PHP 5.3:
$count = 0;
array_walk($array, function($item)
{
if ($item['type'] == 'image')
{
$count++;
}
});
Try this:
function countArray(array $arr, $arg, $filterValue)
{
$count = 0;
foreach ($arr as $elem)
{
if (is_array($elem) &&
isset($elem[$arg]) &&
$elem[$arg] == $filterValue)
$count++;
}
return $count;
}
For your example, you would call it like this:
$result = countArray($array, 'type', 'image');

Categories