PHP数组排序和与波斯语字母表的兼容性

时间:2014-04-01 20:46:08

标签: php arrays sorting

我正在尝试先按照它的值对数组进行排序,然后按它的键进行排序,但是php对波斯语字符的效果不佳。
波斯语字母表类似于阿拉伯字母,除了一些额外的字符,如'گچپژک'和PHP在波斯语字母表中排序阿拉伯字母方面做得很好,但其余的不在他们的顺序中。

例如

$str = 'ا ب پ ت ث ج چ ح خ د ذ ر ز ژ ص ض ط ظ ع غ ف ق ک گ ل م ن و ه ی';
$arr = explode(' ', $str);

将按正确的字母顺序创建一个包含所有波斯语字母的数组($arr)。如果我将其洗牌并使用asort函数如下:

shuffle($arr);
asort($arr);
var_dump($arr);

它会像这样结束:

    array
        2 => string 'ا'
        1 => string 'ب'
        22 => string 'ت'
        29 => string 'ث'
        20 => string 'ج'
        12 => string 'ح'
        21 => string 'خ'
        18 => string 'د'
        6 => string 'ذ'
        3 => string 'ر'
        27 => string 'ز'
        17 => string 'ص'
        11 => string 'ض'
        25 => string 'ط'
        5 => string 'ظ'
        16 => string 'ع'
        8 => string 'غ'
        26 => string 'ف'
        14 => string 'ق'
        9 => string 'ل'
        0 => string 'م'
        7 => string 'ن'
        10 => string 'ه'
        28 => string 'و'
        24 => string 'پ'
        23 => string 'چ'
        13 => string 'ژ'
        19 => string 'ک'
        4 => string 'گ'
        15 => string 'ی'

哪个错了!

第24项应在第1项之后,第23项应在20之后,依此类推。

如何编写与PHP自己的排序函数类似的函数?或者有可能让PHP函数适用于波斯字符?

6 个答案:

答案 0 :(得分:4)

我编写了以下函数来返回任何给定字符的UTF-8代码点:

function utf8_ord($str) {
    $str = (string) $str;
    $ord = ord($str);
    $ord_b = decbin($ord);

    if (strlen($ord_b) <= 7) 
      return $ord;
    $len = strlen(strstr($ord_b, "0", true));

    if ($len < 2 || $len > 4 || strlen($str) < $len) 
      return false;
    $val = substr($ord_b, $len + 1);

    for ($i = 1; $i < $len; $i++) {
        $ord_b = decbin(ord($str[$i]));
        if ($ord_b[0].$ord_b[1] != "10") 
          return false;
        $val. = substr($ord_b, 2);
    }
    $val = bindec($val);
    return (($val > 0x10FFFF) ? null : $val);
}

现在让我们找出数组中字符的UTF-8代码点:

$str = 'ا ب پ ت ث ج چ ح خ د ذ ر ز ژ ص ض ط ظ ع غ ف ق ک گ ل م ن و ه ی';
$arr = explode(' ', $str);
print_r(array_map("utf8_ord", $arr));

输出将是:

Array
(
    [0] => 1575
    [1] => 1576
    [2] => 1662
    [3] => 1578
    [4] => 1579
    [5] => 1580
    [6] => 1670
    [7] => 1581
    [8] => 1582
    [9] => 1583
    [10] => 1584
    [11] => 1585
    [12] => 1586
    [13] => 1688
    [14] => 1589
    [15] => 1590
    [16] => 1591
    [17] => 1592
    [18] => 1593
    [19] => 1594
    [20] => 1601
    [21] => 1602
    [22] => 1705
    [23] => 1711
    [24] => 1604
    [25] => 1605
    [26] => 1606
    [27] => 1608
    [28] => 1607
    [29] => 1740
)

它清楚地表明字符的顺序不正确,需要进行排序。我不知道波斯语,所以我无法确定UTF-8波斯语字母表是否有错。但我只能说PHP正在正常工作。

答案 1 :(得分:0)

我为波斯数组创建了一个自定义javascript排序函数:

var alphabets = ["ا", "ب", "پ", "ت", "ث", "ج", "چ", "ح", "خ", "د",

      "ذ", "ر", "ز", "ژ", "س", "ش", "ص", "ض", "ط", "ظ", "ع", "غ",

      "ف", "ق", "ک", "گ", "ل", "م", "ن", "و", "ه", "ی"];

  function PersianOrder(){

      var persianArrray = ["ایمان", "محمدرضا", "ژوله", "چمدان", "پدرام", "پاشی","پاشا"];

      persianArrray.sort(function (a, b) {

          return CharCompare(a, b, 0);

      });

  }

  function CharCompare(a, b, index) {

      if (index == a.length || index == b.length)

          return 0;

      var aChar = alphabets.indexOf(a.charAt(index));

      var bChar = alphabets.indexOf(b.charAt(index));

      if (aChar != bChar)

          return aChar - bChar

      else

          return CharCompare(a,b,index+1)

  }

Check Online

我希望这个功能可以帮助你

答案 2 :(得分:0)

很好地获取可以使用的可用语言环境

print_r(ResourceBundle::getLocales(''));

我有'fa''fa_IR'可用,但'fa_IR'仍然返回false,所以我使用'fa'来测试它:

setlocale(LC_ALL, 'fa');
asort($arr, SORT_LOCALE_STRING);
var_dump($arr);

但是这还没有按照正确的顺序排序......

所以在更多的谷歌搜索后,最终为我排序Unicode波斯语字母表的解决方案是使用Collator类:

$col = new \Collator('fa_IR');
$col->asort($arr);
var_dump($arr);

我知道问题已经过时了,但这可能仍然有助于新人来到这里寻找这个问题的答案。

答案 3 :(得分:0)

要按波斯字符对数组排序,首先请注意Unicode标准中的某些字符未正确对齐。 在这种情况下,我的建议是创建一个规则的波斯字符数组,并根据该数组排列主题数组。 例如:

function persianSort($item1, $item2){
    $persian_characters = [
        1 =>  'ا',
        2 =>  'ب',
        3 =>  'پ',
        4 =>  'ت',
        5 =>  'ث',
        6 =>  'ج',
        7 =>  'چ',
        8 =>  'ح',
        9 =>  'خ',
        10 =>  'د',
        11 =>  'ذ',
        12 =>  'ر',
        13 =>  'ز',
        14 =>  'ژ',
        15 => 'س',
        16 => 'ش',
        17 =>  'ص',
        18 =>  'ض',
        19 =>  'ط',
        20 =>  'ظ',
        21 =>  'ع',
        22 =>  'غ',
        23 =>  'ف',
        24 =>  'ق',
        25 =>  'ک',
        26 =>  'گ',
        27 =>  'ل',
        28 =>  'م',
        29 =>  'ن',
        30 =>  'و',
        31 =>  'ه',
        32 =>  'ی',
    ];

    if(substr($item1,0,2) == substr($item2,0,2))
        return persianSort(substr($item1,2), substr($item2,2));
    return array_search( substr($item1,0,2), $persian_characters) < array_search( substr($item2,0,2), $persian_characters) ? -1: 1;
}

$states = ['گیلان', 'گرگان', 'یزد', 'سمنان', 'تهران', 'اردبیل', 'کرمان', 'چهار محال بختیاری', 'مشهد', 'اصفهان', 'قم', 'آستارا'];

usort($states, "persianSort");

print_r($states);

上面的代码对伊朗省名的无序数组进行排序。上面代码的输出如下:

Array
(
    [0] => اردبیل
    [1] => اصفهان
    [2] => تهران
    [3] => چهار محال بختیاری
    [4] => سمنان
    [5] => قم
    [6] => کرمان
    [7] => گرگان
    [8] => گیلان
    [9] => مشهد
    [10] => یزد
)

答案 4 :(得分:0)

这是按波斯字母对每个类型数组进行排序的简单方法:

在代码中使用setlocale(LC_ALL,'fa_IR')和SORT_LOCALE_STRING很重要。

多维度数组的示例:

$arr = [
    [
        "name"=> "پژمان",
        "family"=> "رضایی",
        "age"=> "20",
    ],
    [
        "name"=> "بابک",
        "family"=> "قاسمی",
        "age"=> "25",
    ],
    [
        "name"=> "محمد",
        "family"=> "حسینی",
        "age"=> "19",
    ],
    [
        "name"=> "هاشم",
        "family"=> "مقدم",
        "age"=> "28",
    ],
    [
        "name"=> "آفرینش",
        "family"=> "دلربا",
        "age"=> "18",
    ],
    [
        "name"=> "مونا",
        "family"=> "محمدی",
        "age"=> "26",
    ],

];

setlocale(LC_ALL, 'fa_IR');
$faColumns = array_column($arr, 'name');
array_multisort($faColumns, SORT_ASC, SORT_LOCALE_STRING , $arr);

print_r($arr);

索引数组示例

$arr1 = ["پژمان","بابک","محمد","هاشم","آفرینش","مونا"];

setlocale(LC_ALL, 'fa_IR');
asort($arr1, SORT_LOCALE_STRING);

print_r($arr1);

答案 5 :(得分:0)

因为我发现 utf8 表的排序不像波斯字母表的顺序,所以 php 必须对波斯语单词进行排序,因为它们必须排序

<?php 
function persianCmp($a, $b) {
    $per = [
        "آ", "ا", "ب", "پ",
        "ت", "ث", "ج", "چ",
        "ح", "خ", "د", "ذ",
        "ر", "ز", "ژ", "س",
        "ش", "ص", "ض", "ط",
        "ظ", "ع", "غ", "ف",
        "ق", "ک", "گ", "ل",
        "م", "ن", "و", "ه",
        "ی"
    ];    
    $per= array_flip($per);
    $a = $per[mb_strcut($a,0,2)];
    $b = $per[mb_strcut($b,0,2)];
    //echo "\na:".$a." b:".$b;
    if ($a == $b) {
        return 0;
    }
    return ($a < $b) ? -1 : 1;
}
$persianWords = [ "هدیه","حمیدرضا","غلامی","بروجنی","آیه","چرم","بسته"];
var_dump($persianWords);
usort($persianWords, "persianCmp");
var_dump($persianWords);
/*array(7) {
  [0]=>string(8) "هدیه"
  [1]=>string(14) "حمیدرضا"
  [2]=>string(10) "غلامی"
  [3]=>  string(12) "بروجنی"
  [4]=>  string(6) "آیه"
  [5]=>  string(6) "چرم"
  [6]=>  string(8) "بسته"
}
array(7) {
  [0]=>  string(6) "آیه"
  [1]=>  string(12) "بروجنی"
  [2]=>  string(8) "بسته"
  [3]=>  string(6) "چرم"
  [4]=>  string(14) "حمیدرضا"
  [5]=>  string(10) "غلامی"
  [6]=>  string(8) "هدیه"
*/