PHP: Почему флаг SORT_LOCALE_STRING работает не так, как ожидалось? [Дубликат]

Вот реализация Node.js, которая, скорее всего, будет bit.ly. генерируют очень случайную 7-значную строку. используя криптографию Node.js для генерации высоко случайных 25 символов, чем случайный выбор 7 символов.

var crypto = require("crypto");
exports.shortURL = new function () {
    this.getShortURL = function () {
        var sURL = '',
            _rand = crypto.randomBytes(25).toString('hex'),
            _base = _rand.length;
        for (var i = 0; i < 7; i++)
            sURL += _rand.charAt(Math.floor(Math.random() * _rand.length));
        return sURL;
    };
}
15
задан Jani Uusitalo 6 June 2016 в 14:49
поделиться

6 ответов

Если вы хотите использовать собственное решение, поэтому я могу предложить этот

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

Не уверен, это лучшее решение, но оно работает для меня =)

1
ответ дан Amir Djaminov 18 August 2018 в 08:28
поделиться
  • 1
    хороший, отличный. – Eir 5 October 2017 в 10:51
  • 2
    Небольшое обновление, связанное с php 7 и новым оператором «космический корабль». Вы можете использовать & lt; = & gt; для возврата 1 или -1 в последнем условии. – Amir Djaminov 28 April 2018 в 13:40

Я думаю, вы можете использовать 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 -reconfigure locales для добавления локалей.

9
ответ дан Fy- 18 August 2018 в 08:28
поделиться

У меня возникло бы желание перебирать массив и преобразовывать его в английские символы перед сортировкой. Например,

<?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);
?>

Вероятно, не самый лучший с точки зрения скорости обработки / используемых ресурсов. Но уверен, что это облегчает понимание кода.

Edit:

Думая об этом сейчас, вам может быть лучше использовать какую-то таблицу поиска, что-то вроде этого:

<?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);
?>
1
ответ дан Nick 18 August 2018 в 08:28
поделиться
  • 1
    Почему вы предлагаете nl_BE? (Голландский, как говорят / записаны в Бельгии) – middus 28 October 2011 в 14:46
  • 2
    Честно говоря, это был первый язык, который пришел на ум, который будет работать с учетом этого набора данных. Думая об этом сейчас, он может лучше использовать таблицу преобразования, вместо этого, если набор данных будет использовать другие ненормальные символы. – Nick 28 October 2011 в 14:55

Что касается 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

A назад я написал UTF-8 в ASCII инструмент, который преобразует «älph # bla» в «aelph-bla». Вы можете использовать это для «нормализации» вашего ввода, чтобы сделать его сортируемым. Это в основном замена, аналогичная тому, что сказал @Nick.

Вы должны использовать отдельный массив для сортировки, поскольку вызов urlify () в обратном вызове usort () будет тратить массу ресурсов. попробуйте

<?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 или встроенный PECL, попробуйте решение @ Thai, похоже, сладкое!

1
ответ дан rodneyrehm 18 August 2018 в 08:28
поделиться

Этот скрипт должен быть выполнен по-своему. Надеюсь, это поможет. Обратите внимание на функцию mb_strtolower. Вы должны использовать его, чтобы сделать регистр функции нечувствительным. Причина, по которой я не использовал функцию strtolower, заключается в том, что она не очень хорошо работает со специальными символами.

<?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');

EDIT: Извините. Я совершил много ошибок в последнем коде. Теперь проверено.

EDIT {2}: все с многобайтовыми функциями.

5
ответ дан sectus 18 August 2018 в 08:28
поделиться
  • 1
    К сожалению, это не сработает, так как $a[$i] вернет один байт из строки, а не один символ. – Leonid Shevtsov 28 October 2011 в 14:49
  • 2
    Раньше, да, вы были правы. Я изменил алгоритм несколько минут назад. Использование str_split будет работать. – Jaison Erick 28 October 2011 в 15:00
  • 3
    str_split также не обрабатывает многобайтовые строки. :) См. php.net/manual/en/function.mb-split.php#99851 – Leonid Shevtsov 28 October 2011 в 15:04
  • 4
    Ты прав. Я обновлялся до многобайтовой везде. – Jaison Erick 28 October 2011 в 15:12
  • 5
    +1 для решения таблицы поиска. – Billy ONeal 28 October 2011 в 15:28

intl поставляется в комплекте с PHP с PHP 5.3 и , он поддерживает только 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
)
29
ответ дан Thai 18 August 2018 в 08:28
поделиться
Другие вопросы по тегам:

Похожие вопросы: