如何计算数组值并仅保留相关的值?

I have an array that contains multiple integers, I'm interested only in integers that repeat themselves a certain number of times. For example:

$items = (0, 0, 0, 1, 1, 2, 3, 3, 3)

I want to know which item(s) are repeated exactly $number (in this example $number = 3) times (in this example new array $items = (0, 3)).

If none of the array items is repeated $number times, I need to have var $none = 1.

I know for a function array_count_values but don't know how to implement it to my case...

$number = 3;
$items = array_keys(array_filter(array_count_values($items), create_function('$n', "return \$n == $number;")));
if (!$items) {
    $none = 1;
}
  • use array_count_values to get a pairing of how often each number occurs
  • filter this through an array_filter callback that discards all entries except those that have a count of $number
  • take the keys of the resulting array (the actual counted values)
  • the resulting array is either empty or contains the values that occur $number of times

$repeated_items will be an array containing only your desired items.

$limit = 3; //your limit for repetition
$catch = array();
foreach ($items as $item){
    if(array_key_exists($item, $catch)){
     $catch[$item]++;
    } else {
    $catch[$item] = 1;
    }
}
$repeated_items = array();
foreach ($catch as $k=>$caught){
   if($caught>=$limit){
    $repeated_items[]=$k;
   }
}

Some pseudo-code to get you started:

Sort your array in order to get similar items together
Foreach item
    if current item == previous item then
        repeat count ++
    else
        if repeat count > limit then
            add current item to new array
$items = array(0, 0, 0, 1, 1, 2, 3, 3, 3);
$count = array_count_values($items);
$number = 3;
$none = 1;
$result = array();
foreach(array_unique($items) as $item) {
        if($count[$item] == $number) {
                $result[] = $item;
                $none = 0;                                                      
        }
}
$items = array(0, 0, 0, 1, 1, 2, 3, 3, 3);
$none=1;
$new_array=array();
$n=3;
dojob($items,$n,$none,$new_array);
function dojob($items,$n,&$none,&$new_array)
{
    $values_count=array_count_values($items);
    foreach($values_count as $value => $count)
    {
      if($count ==$n)
      {
        $none=0;
        $new_array[]=$value;
      }
    }
}

A bit late, but:

<?php
$items = array(0, 0, 0, 1, 1, 2, 3, 3, 3);
$temp = array_unique($items);
$result = array();
$none = 1;
$number = 3;
foreach($temp as $tmp)
{
    if(count(array_keys($items, $tmp)) == $number)
    {
        array_push($result,$tmp);
        $none = 0;
    }
}
print_r($result);
?>

I know there are a lot of solutions, but thought I'd add one more. ;-)

function array_repeats($items,$repeats,&$none){
  $result = array();
  foreach (array_unique($items) as $item){
    $matches = array_filter($items,create_function('$a','return ($a=='.$item.');'));
    if (count($matches) == $repeats)
      $result[] = $item;
  }
  $none = (count($result)?1:0);
  return $result;
}

DEMO

One way would be to create a kind of hash table and loop over every item in your array.

$items = array(0, 0, 0, 1, 1, 2, 3, 3, 3);
$number = 3;
$none = 1;

foreach ($items as $value) {
    if ($hash[$value] >= $number) {
        # This $value has occured as least $number times. Lets save it.
        $filtered_items[] = $value;

        # We have at least one item in the $items array >= $number times
        # so set $none to 0
        $none = 0;

        # No need to keep adding
        continue;
    } else {
        # Increment the count of each value
        $hash[$value]++;
    }
}

$items = $filtered_items;
$items = array(0, 0, 0, 1, 1, 2, 3, 3, 3);
$icnt = array_count_values($items);
function eq3($v) {
    return $v==3;
}
var_export(array_filter($icnt, 'eq3'));

will produce array ( 0 => 3, 3 => 3, ). In your example 0 and 3 repeat 3 times. Array_filter is needed here to, actually, filter your resulting array and get rid of necessary values, but you was right about using array_count_values here.