rob.m
rob.m

Reputation: 10571

Count duplicate values in an array

I have a series of user data which each one is a list of comma separate values like italian, english. So first of all, I want to list each of them and that it is fine and works. But these values could be repeated and it is ok yet I would like to know the number of the repeated values in order to be able to says: American = 2. The code below shows me

Duplicates count: 5

But actually I should have only 2 duplicates as I can see from the admin panel

$stack = array();
$blogusers = get_users( 'orderby=nicename&role=author' );
foreach ( $blogusers as $user ) {
    $descTokens = explode(',', $user->user_description);
    $stack = array_merge($stack, $descTokens);
}
$count_values = array();
foreach ($stack as $a) {
    @$count_values[$a]++;
}
echo 'Duplicates count: '.count($count_values);

If I do print_r($count_values) i get

Array (
    [francese] => 1
    [ matematica] => 2
    [ inglese] => 1
    [fisica] => 1
    [ latino] => 1
)
Duplicates count: 5

And those aren't repeated strings.

Upvotes: 0

Views: 4665

Answers (3)

Qirel
Qirel

Reputation: 26450

Using array_count_values() you would get the same output as your secondary foreach loop. A count() of this would, by your example, give you 5 - francese, matematica, inglese, fisica and latino would be entries with at least 1 as the value and counted as one each (by your example, the index 'matematica' would hold the value 2 instead of 1, as its a duplicate and appears twice, but will still be counted as one).

So if you then filter away all values which appears once, you should get what you're looking for. Use array_map() with a callback that removes all values that are one or less would be like this

foreach ($blogusers as $user) {
    $descTokens = explode(',', $user->user_description);
    $stack = array_merge($stack, $descTokens);
}
echo array_sum(array_map((function ($v) { return $v > 1 ? $v : 0; }), array_count_values($stack)));

Live demo


If you want an array with the values which only appears multiple times, you can replace array_sum() with array_filter() (that returns an array, so you can no longer echo it directly)

print_r(array_filter(array_map((function ($v) { return $v > 1 ? $v : 0; }), array_count_values($stack))));

Outputs

Array (  
    [twice] => 2  
)

See https://3v4l.org/WOObc for a working example on that.

Upvotes: 2

Manuel Otto
Manuel Otto

Reputation: 6540

Add this at the end of your code to only have duplicates in $count_values

$total_duplicates = 0;
foreach ($count_values as $key=>$count) {
    if($count<=1){
        unset($count_values[$key]);
    }else{
        $total_duplicates += $count;
    }
}

This will remove any entries that are not duplicate (occuring once) via unset(). Also $total_duplicates will give you the total count of duplicates.

To output that as html do this:

echo '<p>You have '.$total_duplicates.' duplicates.</p>';
foreach ($count_values as $key=>$count) { 
    echo '<li>'.$key.' '.$count.'</li>'; 
}

Upvotes: 1

flex_
flex_

Reputation: 733

//Count of the duplicate array values 
$count = count(array_count_values($stack));
echo $count;

Upvotes: 1

Related Questions