0

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.

7
  • 1
    array_count_value does this for you Commented Apr 10, 2017 at 23:56
  • Can you give some examples of the arrays, the actual data? Commented Apr 10, 2017 at 23:57
  • @flex_ may you elaborated it in an answer pease? Commented Apr 10, 2017 at 23:57
  • @Qirel i have updated the question with the print_r result i get Commented Apr 10, 2017 at 23:57
  • So you have 1 duplicate value, which is present two times in your array? Commented Apr 11, 2017 at 0:01

3 Answers 3

2

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.

Sign up to request clarification or add additional context in comments.

1 Comment

Using array_* functions often simplify working with arrays very much - then you don't have to loop as much, and there's almost always a function suitable for what you need ;-) This can of course be split into more lines, which could help readability of the code.
1

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>'; 
}

5 Comments

ok great, this gives me the correct number. Now is it possible to place this result next to each list in order to find out how many of the same are in place? Like Italian 2
with list you mean $stack?
oh sorry, i mean that then i output them as <li><?php echo $stack[0]; ?></li> <li><?php echo $stack[1]; ?></li> and ideally I would like to be able to have a count for each
So $stack[0]; + Num etc will auto generate? Can you elaborate it more in your answer please? I think this is getting right where I what I was looking for
sure just iterate through $count_values again: foreach ($count_values as $key=>$count) { echo '<li>'.$key.' '.$count.'</li>'; }
1
//Count of the duplicate array values 
$count = count(array_count_values($stack));
echo $count;

5 Comments

that gives me 5, it doesn't tell me "you have 2 of this and 3 of that"
@rob.m you did not ask for "you have 2 of this and 3 of that" in your question. You only complained that the overall number of duplicates is wrong.
i don't really know if that's possible. but then again i'm not good at arrays
if i do this i'm almost there $count_values = array(); foreach ($stack as $a) { @$count_values[$a]++; } print_r(array_count_values($count_values));
yet that results number Array ( [1] => 4 [2] => 1 should be placed correctly next to each list results )

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.