简体   繁体   中英

PHP Arrays - Separate Identical Values

Is there any good or standard way of doing this?

Take the following example:

$values = array(
    'blue'
    , 'blue'    
    , 'blue'
    , 'blue'
    , 'green'
    , 'red'
    , 'yellow'
    , 'yellow'
     , 'purple'
    , 'purple'
    , 'purple'
);

I need it to be separated so no two identical values are touching (unless there is no possible solution -- in which case either generating an error, returning false or anything else is acceptable).

Here's the above array (done by hand) but how I am trying to change it:

$values = array(
    'blue'
    , 'purple'
    , 'green'
    , 'purple'
    , 'blue'
    , 'red'
    , 'blue'
    , 'yellow'
    , 'blue'
    , 'yellow'
    , 'purple'
)

The values won't necessarily be in order in the beginning -- that was just for simplicities sake.

Any ideas? Any code to get me started in the right direction?

This function should do the trick:

function uniq_sort($arr){
    if(!count($arr))
        return array();

    $counts = array_count_values($arr);
    arsort($counts);
    while(NULL !== ($key = key($counts)) && $counts[$key]){
        if(isset($prev) && $prev == $key){
            next($counts);
            $key = key($counts);
            if($key === NULL)
                return false;
        }
        $prev = $result[] = $key;

        $counts[$key]--;
        if(!$counts[$key])
            unset($counts[$key]);

        arsort($counts);
        reset($counts);
    }
    return $result;
}

Example usage:

$values = array('blue', 'blue', 'blue', 'blue', 'green', 'red', 'yellow', 'yellow', 'purple', 'purple', 'purple');
print_r(uniq_sort($values));

$values = array('a', 'b', 'b');
print_r(uniq_sort($values));

$values = array(1);
print_r(uniq_sort($values));

$values = array(1, 1, 1, 1, 2, 3, 4);
print_r(uniq_sort($values));

$values = array(1, 1, 1, 1, 2, 3);
var_dump(uniq_sort($values));

And output:

Array
(
    [0] => blue
    [1] => purple
    [2] => blue
    [3] => yellow
    [4] => blue
    [5] => purple
    [6] => blue
    [7] => purple
    [8] => red
    [9] => yellow
    [10] => green
)
Array
(
    [0] => b
    [1] => a
    [2] => b
)
Array
(
    [0] => 1
)
Array
(
    [0] => 1
    [1] => 3
    [2] => 1
    [3] => 4
    [4] => 1
    [5] => 2
    [6] => 1
)
bool(false)
$values = array(
        'blue'
        , 'blue'    
        , 'blue'
        , 'blue'
        , 'green'
        , 'red'
        , 'yellow'
        , 'yellow'
        , 'purple'
        , 'purple'
        , 'purple'
    );
    $value_count = Array();
    foreach($values as $v){
        if(isset($value_count[$v])){
            $value_count[$v]++;
        }else{
            $value_count[$v] = 1;
        }
    }
    unset($v);
    //Now generate new array 
    $result = Array();//This line is technically not necessary 
    $done = false;
    while(!$done){
        $done = true;
        foreach($value_count as $k => &$c){
            if($c > 0){
                $result[] = $k;
                $c--;
                $done = false;
            }
        }
    }
    print_r($result);

This results in this:

Array
(
    [0] => blue
    [1] => green
    [2] => red
    [3] => yellow
    [4] => purple
    [5] => blue
    [6] => yellow
    [7] => purple
    [8] => blue
    [9] => purple
    [10] => blue
)

the logical:

print the first value, before print the next, compare it to the previous one, if they are same, jump over the next and so on.

Walk down the array, remember the last value you saw, and throw away the one you're looking at if it matches. Here's an example :

$values = array(
    'blue'
    , 'blue'    
    , 'blue'
    , 'blue'
    , 'green'
    , 'red'
    , 'yellow'
    , 'yellow'
     , 'purple'
    , 'purple'
    , 'purple'
);

$last_seen_value = NULL;
foreach ($values as $i => $value) {
  if (0 == strcmp($value, $last_seen_value)) {
    unset($values[$i]);
  } else {
    $last_seen_value = $value;
  }
}

print_r($values);

# Output:
# 
# Array
# (
#     [0] => blue
#     [4] => green
#     [5] => red
#     [6] => yellow
#     [8] => purple
# )

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM