PHP array - count unique IDs - php

I have a PHP array that looks like this
Array
(
[0] => Array
(
[events] => Array
(
[0] => Array
(
[label] => apple
[id] => 3
)
[1] => Array
(
[label] => onion
[id] => 3
)
[2] => Array
(
[label] => pear
[id] => 2
)
[3] => Array
(
[label] => orange
[id] => 1
)
[4] => Array
(
[label] => grape
[id] => 41
)
)
)
)
I am trying to get a total count of unique IDs, so in the example above I would want to get a count of 4
Do I need to loop through the array or is there a function that can do it more efficiently? Currently it is a small data set but it could grow fairly large.

You can use array_column to get all the IDs, and array_unique to remove the duplicates, then count that.
count(array_unique(array_column($array[0]['events'][0], 'id')))

One way or another you'll have to loop through it. I think most efficiently would be
function getUnique($arr){
$val = array();
foreach($arr[0]["events"] as $v){
$val[$v["id"]] = true;
}
return count($val);
}

Related

How to merge three arrays according to common key in php

I have three arrays first array include ids and employees name and second array have monthly collection with employee ids and third array have daily collection with employee id and daily collection I want to merge these array with ids and name and dcollection and monthly collection but the desired output is not coming here my first array $ids is
Array
(
[0] => stdClass Object
(
[id] => 1
[name] => Rohit
)
[1] => stdClass Object
(
[id] => 2
[name] => Emop1
)
[2] => stdClass Object
(
[id] => 3
[name] => Pankaj
)
[3] => stdClass Object
(
[id] => 4
[name] => tejpal singh
)
)
second array $q1 is
Array
(
[0] => stdClass Object
(
[name] => Rohit
[id] => 1
[mcollecton] => 100
)
[1] => stdClass Object
(
[name] => Emop1
[id] => 2
[mcollecton] => 1222
)
)
third array $q2 is
Array
(
[0] => stdClass Object
(
[name] => Rohit
[id] => 1
[dcollecton] => 300
)
[1] => stdClass Object
(
[name] => Emop1
[id] => 2
[dcollecton] => 150
)
)
so far what I have tried
$new_array = array();
foreach($ids as $k) {
$q1n = array("id"=>$k->id,"name"=>$k->name);
foreach($q1 as $k1) {
if($k->id==$k1->id){
$mc = array("mc"=>$k1->mcollecton);
array_merge($q1n,$mc);
}
}
foreach($q2 as $k1){
if($k->id==$k1->id){
$dc = array("dc"=>$k1->dcollecton);
array_merge($q1n,$dc);
}
}
$a = array_merge($q1n,$mc);
$av = array_merge($q1n,$dc);
array_push($new_array,$q1n);
}
but the output is coming as
Array
(
[0] => Array
(
[id] => 1
[name] => Rohit
)
[1] => Array
(
[id] => 2
[name] => Emop1
)
[2] => Array
(
[id] => 3
[name] => Pankaj
)
[3] => Array
(
[id] => 4
[name] => tejpal singh
)
)
I want the output be like
Array
(
[0] => Array
(
[id] => 1
[name] => Rohit
[mcollection] => 100
[dcollection] => 300
)
[1] => Array
(
[id] => 2
[name] => Emop1
[mcollection] => 1222
[dcollection] => 150
)
[2] => Array
(
[id] => 3
[name] => Pankaj
[mcollection] => 0
[dcollection] => 0
)
[3] => Array
(
[id] => 4
[name] => tejpal singh
[mcollection] => 0
[dcollection] => 0
)
)
So I have tried many times but the desired output is not coming . please help me out how to get the desired output.
It seemed like that answer could be modified, or put in a function that you could call multiple times if needed to combine more than two arrays.
There's probably cleaner ways to handle this with array functions like array_merge or array_walk, but this is the general idea of how I might approach it. I haven't tested this, but maybe it's useful.
foreach($first as $key1 => $value){
foreach($second as $key2 => $value2){
// match the ids and check if array key exists on first array
if($value['id'] === $value2['id'] && empty($first[$key2])){
$first[$key][$key2] = $value2;
}
}
}
EDIT: Based on the answer you posted vs the question you asked, are you incrementing the collection numbers or just setting them? In other words why use +=? You should also be able to remove array_merge and array_push.
Below is geared more towards what you're trying to do. I haven't tested this either, but if you run into errors, post your code with the errors returned so that it's easier to debug:
foreach($ids as $k)
{
$thisArray = $newArray[] = array("id"=>$k->id,"name"=>$k->name);
foreach($q1 as $k1)
{
if($k->id == $k1->id && !empty($k1->mcollecton))
{
$thisArray['mc'] = $k1->mcollecton;
}
}
foreach($q2 as $k2)
{
if($k->id == $k2->id && !empty($k2->dcollecton))
{
$thisArray['dc'] = $k2->dcollecton;
}
}
}
// This should have both new collections fields on all array items
print_r($newArray)

How to match and relate data unique?

I'm having some difficulties figuring out how to return the best unique match, while assigning as many as possible.
Scenario: Each kid has a list of favorite fruits with a personal score. We only have ONE of each fruit, so we want to give it to the kid with the highest preference. One can be left without fruit if someone has a higher score, but we still want to give out as many fruits as possible.
The expected result would be:
0 = [1] Apple
1 = [0] Mango
2 = [0] Banana
3 = null
This is my input array:
Array
(
[0] => Array
(
[0] => Array
(
[name] => Banana
[score] => 80.2
)
[1] => Array
(
[name] => Apple
[score] => 40
)
)
[1] => Array
(
[0] => Array
(
[name] => Mango
[score] => 70
)
[1] => Array
(
[name] => Banana
[score] => 40
)
)
[2] => Array
(
[0] => Array
(
[name] => Banana
[score] => 90
)
[1] => Array
(
[name] => Orange
[score] => 20
)
)
[3] => Array
(
[0] => Array
(
[name] => Mango
[score] => 60
)
)
)
My approach first flattens your input into a simple 2D array allowing all rows to be sorted by score while preserving the fruit and childid data. After sorting, all rows are iterated (versus doing iterated full-array searches) and only stores the most preferred fruit, if available, for each child as requested.
OP's Input:
$input=[
[['name'=>'Banana','score'=>80.2],['name'=>'Apple','score'=>40]],
[['name'=>'Mango','score'=>70],['name'=>'Banana','score'=>40]],
[['name'=>'Banana','score'=>90],['name'=>'Orange','score'=>20]],
[['name'=>'Mango','score'=>60]]
];
Method:
$result=array_fill_keys(array_keys($input),null); // list all child ids and default to null
// flatten input array for simple sorting and iteration
foreach($input as $i=>$subarrays){
foreach($subarrays as $a){
$restructured[]=['score'=>$a['score'],'fruit'=>$a['name'],'childid'=>$i];
}
}
rsort($restructured); // will sort the array by score DESC
foreach($restructured as $a){
if(is_null($result[$a['childid']]) && !in_array($a['fruit'],$result)){
// only "fruitless" children wanting what is available
$result[$a['childid']]=$a['fruit'];
}
}
var_export($result);
Output:
array (
0 => 'Apple',
1 => 'Mango',
2 => 'Banana',
3 => NULL,
)

Multidimensional Array - Get unique values, but count all duplicates

I have a multi-dimensional array that I would like to get unique sub-values from, but also have a count of how many times those unique sub-values occurred.
For instance, this would be my starting array:
[0] => Array
(
[0] => Array
(
[id] => 1533438473619168
)
[1] => Array
(
[id] => 3333333333333333
)
)
[1] => Array
(
[0] => Array
(
[id] => 1533438473619168
)
[1] => Array
(
[id] => 5555555555555555
)
)
[2] => Array
(
[0] => Array
(
[id] => 1533438473619168
)
[1] => Array
(
[id] => 77777777777777777
)
)
In the end, I'd like to have an array that looks like this:
[0] => Array
(
[0] => Array
(
[id] => 1533438473619168
[count] => 3
)
[1] => Array
(
[id] => 3333333333333333
[count] => 1
)
[2] => Array
(
[id] => 5555555555555555
[count] => 1
)
[3] => Array
(
[id] => 77777777777777777
[count] => 1
)
)
Is there any general/easy way to do this without iterating through the first array for each value, comparing/storing the values in a temporary array, checking them, and adding to the count?
To get this exact format you may need to iterate thought your current array and do the counting manually, however php has the array_count_values() and array_unique() functions for this kind of thing:
http://php.net/manual/en/function.array-count-values.php
http://php.net/manual/en/function.array-unique.php
Because you are only concerned with the deepest values of the array, using array_walk_recursive seems suitable for this. Note that a reference to the output array $counted is used in the callback.
array_walk_recursive($ids, function($id, $k) use (&$counted) {
$counted[$id] = isset($counted[$id]) ? $counted[$id] + 1 : 1;
});
Using the id as the key in the $counted array will simplify the counting. The result of this will be somewhat different from your suggested output, but in my opinion it would actually be simpler to use. (e.g. foreach ($counted as $id => $count) {...).
$counted = array(
"1533438473619168" => 3
"3333333333333333" => 1
"5555555555555555" => 1
"77777777777777777" => 1);

Combine and sum values in multi-dimensional associative array using php

I have an associative array that looks like this:
Array (
[0] => Array (
[amount] => 3
[name] => Chuck
)
[1] => Array (
[amount] => 2
[name] => Steve
)
[2] => Array (
[amount] => 5
[name] =>
)
[3] => Array (
[amount] => 4
[name] => Chuck
)
[4] => Array (
[amount] =>
[name] => Chuck
)
)
I need to remove values that are missing a name or amount e.g. [2] and [4] and then sum the totals for each name so that the final array is:
Array (
[0] => Array (
[amount] => 7
[name] => Chuck
)
[1] => Array (
[amount] => 2
[name] => Steve
)
)
For anyone looking for this nowadays, this would be much cleaner:
$sum = array_sum(array_column($data, 'amount'));
Try this:
$starting_array = array( ... ); // Initial array with your setup
$final_array = array();
$sum = 0;
foreach ($starting_array as $idx => $data) {
if (!empty($data['amount']) && !empty($data['name'])) {
$final_array[$idx] = $data;
$sum += $data['amount'];
}
}
// After looping through all of the items, $final_array should contain all
// of the specific items that have an amount and name set. In addition, the
// total of all of the amounts will be in $sum.
Take a look at php's empty(). Note: If 0 is an allowed value, you may want to use is_null() instead.

php merging two arrays into one

I have two arrays that need to be merged together and trying to figure out the correct way of doing it.
this is the first array
Array
(
[IndividualOutmsg] => Array
(
[0] => Array
(
[user_id] => 3
[number] => 414566765
[msg] => some message
)
[1] => Array
(
[user_id] => 3
[number] => 410335509
[msg] => any message
)
)
)
this is the second array:
Array
(
[0] => Array
(
[0] => OK
[1] => 0
[2] => d142b46128b869d0
[3] => 6178977058476937
)
[1] => Array
(
[0] => OK
[1] => 0
[2] => 60f403f4e243e684
[3] => 6198708709873543
)
)
what i want to get is this:
Array
(
[IndividualOutmsg] => Array
(
[0] => Array
(
[user_id] => 3
[number] => 414566765
[msg] => some message
[sms_status] => OK
[error_code] => 0
[msg_id] => d142b46128b869d0
[msg_id_2] => 6178977058476937
)
[1] => Array
(
[user_id] => 3
[number] => 410335509
[msg] => any message
[sms_status] => OK
[error_code] => 0
[msg_id] => 60f403f4e243e684
[msg_id_2] => 6198708709873543
)
)
)
In that format, you really have to do a lot of the legwork yourself and can't just use array_merge to combine the arrays. It would have to be a more custom job, like so:
$count = count($second_array);
for($i=0; $i<$count; $i++){
$first_array['IndividualOutmsg'][$i]['sms_status'] = $second_array[0];
$first_array['IndividualOutmsg'][$i]['error_code'] = $second_array[1];
$first_array['IndividualOutmsg'][$i]['msg_id'] = $second_array[2];
$first_array['IndividualOutmsg'][$i]['msg_id2'] = $second_array[3];
}
If you were to output the second array with the associative keys set, it would be much easier to combine them using array_merge, provided the keys didn't conflict.
$count = count($second_array);
for($i=0; $i<$count; $i++){
$first_array['IndividualOutmsg'][$i] =
array_merge($first_array['IndividualOutmsg'][$i], $second_array[$i]);
}
http://au.php.net/manual/en/function.array-merge.php
Array merge might be what you're looking for...
Though you'll need to probably write a loop or function that can get to the right place in your multi-dimensional array, perform the merge and also change the relevant keys.

Categories