【问题标题】:Sort array string-type keys by a custom alphabet?按自定义字母对数组字符串类型的键进行排序?
【发布时间】:2011-09-15 02:00:09
【问题描述】:

我想在 php 中按键对数组进行排序,但我使用的字母表不是普通的英文字母表——它是一个自行创建的字母表。这可能吗?

我的字母是:

$alphabet = "AjawbpfmnrhHxXsSqkgtTdD =";

数组是这样的:

Array (
   [=k_0] => Array(
       [0] => DI.3,2 &dwA-nTr& @Hrw@
       [1] => mA
       [2] => =k
       [3] => Sfj,t
       [4] => =k
       [5] => pXr
       )
   [aA_2] => Array(
       [0] => DI.7,4 &dwA-nTr& @Hrw-smA-tA,wj@
       [1] => snD
       [2] => aA
       [3] => Sfj,t
       [4] => jt
       [5] => jt,w
       )
  [sqA_1] => Array(
       [0] => DI.6,18 &dwA-nTr& @nswt@
       [1] => ra
       [2] => sqA
       [3] => Sfj,t
       [4] => =s
       [5] => r
       )
   );

因此,如果我按照字母表对这个数组进行排序,那么带有键 [=k_0] 的数组应该在末尾。

【问题讨论】:

  • 自创字母表是什么意思?你如何映射这些?难道你还需要一个整数来表示它吗?
  • 这样的键的任何例子,也许?
  • 字母表是 $alphabet = "AjawbpfmnrhHxXsSqkgtTdD"
  • 字母表是 $alphabet = "AjawbpfmnrhHxXsSqkgtTdD =";数组是这样的: Array ([=k_0] => Array([0] => DI.3,2 &dwA-nTr& @Hrw@ [1] => mA [2] => =k [3] => Sfj,t [4] => =k [5] => pXr ) [aA_2] => 数组( [0] => DI.7,4 &dwA- nTr& @Hrw-smA-tA,wj@ [1] => snD [2] => aA [3] => Sfj,t [4] => jt [5] => jt,w ) [sqA_1] =>数组( [0] => DI.6,18 &dwA-nTr& @nswt@ [1] => ra [2] => sqA [3] => Sfj,t [4] => =s [5] => r));所以如果我按照我的字母表对这个数组进行排序,那么带有键 [=k_0] 的数组应该在最后。

标签: php arrays sorting translation ksort


【解决方案1】:

您可以使用usort() 函数并提供您自己的排序逻辑。

有关示例,请参阅 php.net

编辑:使用uksort,而不是usort。见http://www.php.net/manual/en/function.uksort.php。谢谢@Darien!

来自 php.net 的稍微修改的示例 - 添加了 $alphabet 映射的原始代码:

function cmp($a, $b)
{
    // custom sort order - just swapps 2 and 3.
    $alphabet = array (1 => 1, 2 => 3, 3 => 2, 4 => 4, 5 => 5, 6=> 6);

    if ($alphabet[$a] == $alphabet[$b]) {
        return 0;
    }
    return ($alphabet[$a] < $alphabet[$b]) ? -1 : 1;
}

$a = array(3 => 'c' , 2 => 'b', 5 => 'e', 6 => 'f', 1=>'a');
uksort($a, "cmp");

foreach ($a as $key => $value) {
    echo "$key: $value\n";
}

【讨论】:

  • 是的 - OP 具​​有常规功能未直接涵盖的自定义要求。如果没有详细信息,usort 是一个很好的起点。
  • 我想你的意思是uksort()。 @Oz:是的,我想是的,因为另一种选择——创建自定义语言环境——让我觉得付出了难以置信的努力/矫枉过正。
  • 问题是关于按自定义字母排序,而不仅仅是关于“如何对数组进行排序”。这不是答案,所以 -1。
  • @OZ_:鉴于提供的信息,这是一条积极的路线。如果您能想到更好的方法,请继续发布。
  • 上述功能当然有效,但在我的情况下,键是必须根据预设字母排序的字符串,例如“睡眠”=>“晚上”应该在“清醒”之后=> "morning", 给数组("awake"=>"morning", "sleep" => "evening");但这现在必须不是用英文字母而是用另一个字母来完成 (AjawbpfmnrhHxXsSqkgtTdD=)
【解决方案2】:

查看此代码:

<?php

$arr = array('wr' => 1, 'wrS' => 6, 'wr,w' => 3, 'wr.w' => 4, 'wr-qA' => 2, 'wrs' => 5);

function compare_by_alphabet(array $alphabet, $str1, $str2)
{
    $l1 = strlen($str1);
    $l2 = strlen($str2);
    $c = min($l1, $l2);

    for ($i = 0; $i < $c; $i++)
    {
        $s1 = $str1[$i];
        $s2 = $str2[$i];
        if ($s1===$s2) continue;
        $i1 = array_search($s1, $alphabet);
        if ($i1===false) continue;
        $i2 = array_search($s2, $alphabet);
        if ($i2===false) continue;
        if ($i2===$i1) continue;
        if ($i1 < $i2) return -1;
        else return 1;
    }
    if ($l1 < $l2) return -1;
    elseif ($l1 > $l2) return 1;
    return 0;
}

function compare_keys_by_alphabet($a, $b)
{
    static $alphabet = array('-', ',', '.', 'A', 'j', 'a', 'w', 'b', 'p', 'f', 'm', 'n', 'r', 'h', 'H', 'x', 'X', 's', 'S', 'q', '‌​k', 'g', 't', 'T', 'd', 'D', '=', '/', '(', ')', '[', ']', '<', '>', '{', '}', '\'', '*', '#', 'I', 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, '&', '@');
    return compare_by_alphabet($alphabet, $a, $b);
}

uksort($arr, 'compare_keys_by_alphabet');

print_r($arr);

结果:

Array
(
    [wr] => 1
    [wr-qA] => 2
    [wr,w] => 3
    [wr.w] => 4
    [wrs] => 5
    [wrS] => 6
)

【讨论】:

  • @OZ 你能解释一下以下内容吗?带数组: $arr = array('wr' => 1, 'wrS' => 6, 'wr,w' => 3, 'wr.w' => 4, 'wr-qA' => 2, ' wrs' => 5); $alphabet = array('-','\,','.','A','j','a','w','b','p','f','m', 'n','r','h','H','x','X','s','S','q','k','g','t','T ','d','D','=','/','(',')','[',']','','{','}', '\'','*','#','I',1,2,3,4,5,6,7,8,9,0,'&','@');我得到的输出: Array('[wr.w] => 4', '[wrs] => 5', '[wr,w] => 3', '[wr] => 1', '[wr -qA] => 2', '[wrS] => 6');但我的字母表我想要 Array('[wr] => 1', '[wr-qA] => 2', '[wr,w] => 3', '[wr.w] => 4', '[wrs] => 5', '[wrS] => 6')
  • @Preys,在您的评论中,您写了 2 个相同的数组 :) 只需按值对第一个数组进行排序:asort($arr); 但如果您想按 VALUES 而不是 KEYS 排序,则不需要任何字母,只有asort 函数。
  • 用过python,php中一定有我不明白的地方;程序的结果应该是一个数组,其中有不同的数组。这些不同的数组必须根据键进行排序。所以你的程序将作为第一个数组 "wr.w" => 4;我想要的是第一个数组应该是 "wr" => 1;因为基于字母表,“wr”在“wr.w”之前,就像在我们的字母表中,“bird”在“birds”之前。不同数组(1 或 5 或 6)的值必须没有影响。跨度>
  • @Preys,现在我明白了。请参阅编辑后的答案。请注意,字母表中的, 不应使用反斜杠进行转义。如果您想发送有关此评论的通知,请在评论中写@nickname
【解决方案3】:

给定您的$alphabet = "AjawbpfmnrhHxXsSqkgtTdD";,并假设Aja 等,根据您的评论,将替代字母表中的每个键转换为已知字母表中的系列,例如使用如下映射:

  your alphabet: AjawbpfmnrhHxXsSqkgtTdD
 'real'alphabet: abcdefghijklmnopqrstuvw

所以密钥'Ajaw' =&gt; 'abcd''fmnr' =&gt; 'ghij' 等。然后这会将您的密钥变成您可以使用常规php 函数进行排序的东西。不过,您需要一些方法来处理原始字母表中不存在的字符。

类似的东西可能会起作用 - 你需要两个转换函数(从你的字母表到“真实”字母表,反之亦然),然后是一个比较器,例如uksort.

我的两分钱 - 感谢您澄清最初的问题。

【讨论】:

  • 这对于小文本来说似乎是可能的,但是在处理大量文本时,这似乎是一个很长的弯路才能找到解决方案。我正在寻找类似于 python 中的以下内容: sorted_list = sorted(Unsorted_list, key=lambda (v, k): [alphabet.index(c) for c in v])
  • 我同意 - 这不是一个特别优雅的解决方案。
  • 自己编译 PHP 6,它已经内置了。
  • @hakre 你能把这个php原生函数文档的链接贴出来吗?
  • @Vinicius.Silva 不记得具体了,也许是 strtr ? php.net/strtr - 与 PHP 6 的类比一定是个笑话,它从未发布过。
【解决方案4】:
<?php
$arr = [8,10,12,18,20,7,4,6,2,20,0]; //take array

 $a= sortasc($arr); // call function

function sortasc($arr){


    for($i=0;$i<=count($arr);$i++){
            for($j=1;$j<=count($arr)-1;$j++){

                         if($arr[$j-1]>$arr[$j]){

                        $temp = $arr[$j];
                        $arr[$j]= $arr[$j-1];
                        $arr[$j-1] = $temp;
                    }
        }
    }
        return $arr;
}

?>

【讨论】:

    【解决方案5】:

    在得到@mickmackusa 的反馈后,我更新了我的示例以使用 uksrot 并全面回答问题

    $order = str_split("AjawbpfmnrhHxXsSqkgtTdD");
    
    uksort($arr, function ($a, $b) use ($order) {
        $posA = array_search($a, $order);
        $posB = array_search($b, $order);
        return $posA - $posB;
    });
    

    http://sandbox.onlinephpfunctions.com/code/9b6f39b30dcc932517bbe82608dd8a0c8d35b3da

    -- 使用 usort 的原始响应--

    您可以像这样将 usort() 与自定义订单数组一起使用

    $arr = array("w","b","m","n","x","x","z","T","T","A","A");
    
    $order = array("A","j","a","w","b","p","f","m","n","r","h","H","x","X","s","S","q","k","g","t","T","d","D"," ","=");
        usort($arr, function ($a, $b) use ($order) {
            $posA = array_search($a, $order);
            $posB = array_search($b, $order);
            return $posA - $posB;
        });
    

    (你可能只是分解 $order 字符串,这样更好)

    实际上我刚刚遇到了this 答案,它更好地解释了它,并且如果值不在订单数组中,则进行处理。

    还有一个工作示例http://sandbox.onlinephpfunctions.com/code/3934aafe93377ec18549d326d6551608436242a7

    【讨论】:

    • 我认为这种技术不能按要求工作。请通过提供在线演示来证明它有效。
    • @updated 示例。我不再按原意使用 uksort 和使用 usort
    • OP 不想按值排序。您的演示/答案的核心问题是您忽略了 OP 的要求和示例数据。这个答案不正确。
    • 现在更新以使用示例的答案
    • 您的 sn-p 没有使用 OP 非常清楚地提供的多字符串键。这个答案不考虑比较长于一个字符的键的复杂性。如果您感到困惑,请阅读我新发布的正确答案,该答案尊重 OP 输入数据的复杂性。
    【解决方案6】:

    幸运的是,您的自定义字母表没有比单字节拉丁字母列表更多的字符,因此翻译是一个非常简单易读的过程。

    我建议您在开始排序之前设置一个翻译数组,然后翻译/规范化键以进行排序。

    代码:(Demo)

    $array = [
        '=k_0' => ['test1'],
        'aA_2' => ['test2'],
        'sqA_1' => ['test3'],
        '=kj_0' => ['test4'],
        'awA_2' => ['test5'],
        '= D_1' => ['test6'],
        'sq A_1' => ['test7'],
        'sqA_2' => ['test8'],
    ];
    
    $trans = ['AjawbpfmnrhHxXsSqkgtTdD =', 'abcdefghijklmnopqrstuvwxy'];
    
    uksort(
        $array,
        function ($a, $b) use ($trans) {
            return strtr($a, ...$trans) <=> strtr($b, ...$trans);
        }
    );
    var_export($array);
    

    输出:

    array (
      'aA_2' => 
      array (
        0 => 'test2',
      ),
      'awA_2' => 
      array (
        0 => 'test5',
      ),
      'sqA_1' => 
      array (
        0 => 'test3',
      ),
      'sqA_2' => 
      array (
        0 => 'test8',
      ),
      'sq A_1' => 
      array (
        0 => 'test7',
      ),
      '=k_0' => 
      array (
        0 => 'test1',
      ),
      '=kj_0' => 
      array (
        0 => 'test4',
      ),
      '= D_1' => 
      array (
        0 => 'test6',
      ),
    )
    

    从 PHP7.4 开始,可以使用箭头函数语法来简化语法。

    uksort(
        $array,
        fn($a, $b) => strtr($a, ...$trans) <=> strtr($b, ...$trans)
    );
    

    【讨论】:

    • @hakre 好了^
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-06-11
    • 2012-06-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-10
    • 1970-01-01
    相关资源
    最近更新 更多