代码之家  ›  专栏  ›  技术社区  ›  Blackbam

PHP:为什么标志SORT\u LOCALE\u字符串不能按预期工作?[副本]

  •  0
  • Blackbam  · 技术社区  · 6 年前

    需要帮助按utf-8排序单词。例如,我们有5个来自比利时的城市。

    $array = array('Borgloon','Thuin','Lennik','Éghezée','Aubel');
    sort($array); // Expected: Aubel, Borgloon, Éghezée, Lennik, Thuin
                  // Actual: Aubel, Borgloon, Lennik, Thuin, Éghezée
    

    酥油 应该是第三名。是否可以使用/设置某种utf-8或创建自己的角色顺序?

    0 回复  |  直到 9 年前
        1
  •  39
  •   Thai    13 年前

    intl 与PHP5.3和 it only supports UTF-8 .

    你可以使用 Collator 在这种情况下:

    $array = array('Borgloon','Thuin','Lennik','Éghezée','Aubel');
    $collator = new Collator('en_US');
    $collator->sort($array);
    print_r($array);
    

    输出:

    Array
    (
        [0] => Aubel
        [1] => Borgloon
        [2] => Éghezée
        [3] => Lennik
        [4] => Thuin
    )
    
        2
  •  10
  •   Fy-    13 年前

    我想你可以用 strcoll

    setlocale(LC_COLLATE, 'nl_BE.utf8');
    $array = array('Borgloon','Thuin','Lennik','Éghezée','Aubel');
    usort($array, 'strcoll'); 
    print_r($array);
    

    Array
    (
        [0] => Aubel
        [1] => Borgloon
        [2] => Éghezée
        [3] => Lennik
        [4] => Thuin
    )
    

    你需要nl_BE.utf8型系统上的区域设置:

    fy@Heisenberg:~$ locale -a | grep nl_BE.utf8
    nl_BE.utf8
    

    如果您使用的是debian,那么您可以使用 dpkg—重新配置区域设置 添加区域设置。

        3
  •  8
  •   sectus    8 年前

    <?php
    
    function customSort($a, $b) {
        static $charOrder = array('a', 'b', 'c', 'd', 'e', 'é',
                                  'f', 'g', 'h', 'i', 'j',
                                  'k', 'l', 'm', 'n', 'o',
                                  'p', 'q', 'r', 's', 't',
                                  'u', 'v', 'w', 'x', 'y', 'z');
    
        $a = mb_strtolower($a);
        $b = mb_strtolower($b);
    
        for($i=0;$i<mb_strlen($a) && $i<mb_strlen($b);$i++) {
            $chA = mb_substr($a, $i, 1);
            $chB = mb_substr($b, $i, 1);
            $valA = array_search($chA, $charOrder);
            $valB = array_search($chB, $charOrder);
            if($valA == $valB) continue;
            if($valA > $valB) return 1;
            return -1;
        }
    
        if(mb_strlen($a) == mb_strlen($b)) return 0;
        if(mb_strlen($a) > mb_strlen($b))  return -1;
        return 1;
    
    }
    $array = array('Borgloon','Thuin','Lennik','Éghezée','Aubel');
    usort($array, 'customSort');
    

    编辑:对不起。我在上一段代码中犯了很多错误。现在是考验。

    编辑{2}:使用多字节函数的所有内容。

        4
  •  2
  •   Amir Djaminov    7 年前

    function compare($a, $b)
    {
            $alphabet = 'aąbcćdeęfghijklłmnnoóqprstuvwxyzźż'; // i used polish letters
            $a = mb_strtolower($a);
            $b = mb_strtolower($b);
    
            for ($i = 0; $i < mb_strlen($a); $i++) {
                if (mb_substr($a, $i, 1) == mb_substr($b, $i, 1)) {
                    continue;
                }
                if ($i > mb_strlen($b)) {
                    return 1;
                }
                if (mb_strpos($alphabet, mb_substr($a, $i, 1)) > mb_strpos($alphabet, mb_substr($b, $i, 1))) {
                    return 1;
                } else {
                    return -1;
                }
            }
    }
    
    usort($needed_array, 'compare');
    

        5
  •  1
  •   Nick    13 年前

    我很想在数组中循环并在排序之前转换成英文字符。例如。

    <?php
      $array = array('Borgloon','Thuin','Lennik','Éghezée','Aubel');
    
      setlocale(LC_CTYPE, 'nl_BE.utf8');
    
      $newarray = array();
      foreach($array as $k => $v) {
        $newarray[$k] = iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE', $v);
      }
    
      sort($newarray);
      print_r($newarray);
    ?>
    

    现在想想,最好使用某种查找表,例如:

    <?php
      $accentedCharacters = array ( 'à', 'á', 'â', 'ã', 'ä', 'å', 'ç', 'è', 'é', 'ê', 'ë', 'ì', 'í', 'î', 'ï', 'ñ', 'ò', 'ó', 'ô', 'õ', 'ö', 'ø', 'ù', 'ú', 'û', 'ü', 'ý', 'ÿ', 'Š', 'Ž', 'š', 'ž', 'Ÿ', 'À', 'Á', 'Â', 'Ã', 'Ä', 'Å', 'Ç', 'È', 'É', 'Ê', 'Ë', 'Ì', 'Í', 'Î', 'Ï', 'Ñ', 'Ò', 'Ó', 'Ô', 'Õ', 'Ö', 'Ø', 'Ù', 'Ú', 'Û', 'Ü', 'Ý' ); 
    
      $replacementCharacters = array ( 'a', 'a', 'a', 'a', 'a', 'a', 'c', 'e', 'e', 'e', 'e', 'i', 'i', 'i', 'i', 'n', 'o', 'o', 'o', 'o', 'o', 'o', 'u', 'u', 'u', 'u', 'y', 'y', 'S', 'Z', 's', 'z', 'Y', 'A', 'A', 'A', 'A', 'A', 'A', 'C', 'E', 'E', 'E', 'E', 'I', 'I', 'I', 'I', 'N', 'O', 'O', 'O', 'O', 'O', 'O', 'U', 'U', 'U', 'U', 'Y' );
    
      $array = array('Borgloon','Thuin','Lennik','Éghezée','Aubel');
    
      $newarray = array();
      foreach($array as $k => $v) {
        $newarray[$k] = str_replace($accentedCharacters,$replacementCharacters,$v);
      }
    
      sort($newarray);
      print_r($newarray);
    ?>
    
        6
  •  1
  •   rodneyrehm    13 年前

    至于strcoll,我想这是个好主意,但似乎不管用:

    <?php
    
    // Some 
    $strings = array('Alpha', 'Älpha', 'Bravo');
    // make it German: A, Ä, B
    setlocale(LC_COLLATE, 'de_DE.UTF8', 'de.UTF8', 'de_DE.UTF-8', 'de.UTF-8');
    usort($strings, 'strcoll');
    var_dump($strings);
    // as you can see, Ä is last, so this didn't work
    

    不久前我写了一篇 UTF-8 to ASCII 将“lph#bla”转换为“aelph bla”的工具。您可以使用它来“规范化”您的输入,使其可排序。它基本上是一个类似于@Nick所说的替代品。

    您应该使用单独的数组进行排序,因为在usort()回调中调用urlify()会浪费大量资源。尝试

    <?php
    // data to sort
    $array = array('Borgloon','Thuin','Lennik','Éghezée','Aubel');
    // container for modified strings
    $_array = array();
    foreach ($array as $k => $v) {
        // "normalize" utf8 to ascii
        $_array[$k] = urlify($v);
    }
    // sort the ASCII stuff (while preserving indexes)
    asort($_array);
    foreach ($_array as $key => &$v) {
        // copy the original value of the ASCIIfied element
        $v = $array[$k];
    }
    var_dump($_array);
    

    如果你已经编译了PHP5.3或者intl-PECL,试试@Thai的解决方案,看起来很不错!

        7
  •  1
  •   Heath Dutton    5 年前

    function globalsort($array, $in = 'UTF-8', $out = 'ASCII//TRANSLIT//IGNORE')
    {
        return usort($array, function ($a, $b) use ($in, $out) {
            $a = @iconv($in, $out, $a);
            $b = @iconv($in, $out, $b);
            return strnatcasecmp($a, $b);
        });
    }
    

    像这样使用:

    globalsort($array);