Best solution to remove duplicate values from case

2020-03-21 11:06发布

问题:

I found a few solutions but I can't decide which one to use. What is the most compact and effective solution to use php's array_unique() function on a case-insensitive array?

Example:

$input = array('green', 'Green', 'blue', 'yellow', 'blue');
$result = array_unique($input);
print_r($result);

Result:

Array ( [0] => green [1] => Green [2] => blue [3] => yellow )

How do we remove the duplicate green? As far as which one to remove, we assume that duplicates with uppercase characters are correct.

e.g. keep PHP remove php

or keep PHP remove Php as PHP has more uppercase characters.

So the result will be

Array ( [0] => Green [1] => blue [2] => yellow )

Notice that the Green with uppercase has been preserved.

回答1:

Would this work?

$r = array_intersect_key($input, array_unique(array_map('strtolower', $input)));

Doesn't care about the specific case to keep but does the job, you can also try to call asort($input); before the intersect to keep the capitalized values instead (demo at IDEOne.com).



回答2:

If you can use PHP 5.3.0, here's a function that does what you're looking for:

<?php
function array_unique_case($array) {
    sort($array);
    $tmp = array();
    $callback = function ($a) use (&$tmp) {
        if (in_array(strtolower($a), $tmp))
            return false;
        $tmp[] = strtolower($a);
        return true;
    };
    return array_filter($array, $callback);
}

$input = array(
    'green', 'Green', 
    'php', 'Php', 'PHP', 
    'blue', 'yellow', 'blue'
);
print_r(array_unique_case($input));
?>

Output:

Array
(
    [0] => Green
    [1] => PHP
    [3] => blue
    [7] => yellow
)


回答3:

function count_uc($str) {
  preg_match_all('/[A-Z]/', $str, $matches);
  return count($matches[0]);
}

$input = array(
    'green', 'Green', 'yelLOW', 
    'php', 'Php', 'PHP', 'gREEN', 
    'blue', 'yellow', 'bLue', 'GREen'
);

$input=array_unique($input);
$keys=array_flip($input);
array_multisort(array_map("strtolower",$input),array_map("count_uc",$input),$keys);
$keys=array_flip(array_change_key_case($keys));
$output=array_intersect_key($input,$keys);
print_r( $output );

will return:

Array
(
    [2] => yelLOW
    [5] => PHP
    [6] => gREEN
    [9] => bLue
)


回答4:

You should first make all values lowercase, then launch array_unique and you are done



回答5:

Normalize your data first by sending it through strtoupper() or strtolower() to make the case consistent. Then use your array_unique().

$normalized = array_map($input, 'strtolower');
$result = array_unique($normalized);
$result = array_map($result, 'ucwords');
print_r($result);