【问题标题】:How to sort an array with PHP, ignoring the articles (a, an, the) in the beginning?如何用PHP对数组进行排序,忽略开头的文章(a,an,the)?
【发布时间】:2013-12-23 13:54:18
【问题描述】:

假设我有以下数组$books(实际数组要大得多):

Array
(
    [0] => The Mystic Masseur
    [1] => The Suffrage of Elvira
    [2] => Miguel Street
    [3] => A House for Mr Biswas
    [4] => Mr Stone and the Knights Companion
    [5] => The Mimic Men
    [6] => A Flag on the Island
    [7] => In a Free State
    [8] => Guerrillas
    [9] => A Bend in the River
    [10] => The Enigma of Arrival
    [11] => A Way in the World
    [12] => Half a Life
    [13] => Magic Seeds
)

当我使用sort函数时,结果是这样的:

Array
(
    [0] => A Bend in the River
    [1] => A Flag on the Island
    [2] => A House for Mr Biswas
    [3] => A Way in the World
    [4] => Guerrillas
    [5] => Half a Life
    [6] => In a Free State
    [7] => Magic Seeds
    [8] => Miguel Street
    [9] => Mr Stone and the Knights Companion
    [10] => The Enigma of Arrival
    [11] => The Mimic Men
    [12] => The Mystic Masseur
    [13] => The Suffrage of Elvira
)

但我想忽略开头的文章(a,an,the),并希望得到这样的结果:

Array
(
    [0] => A Bend in the River
    [1] => The Enigma of Arrival
    [2] => A Flag on the Island
    [3] => Guerrillas
    [4] => Half a Life
    [5] => A House for Mr Biswas
    [6] => In a Free State
    [7] => Magic Seeds
    [8] => Miguel Street
    [9] => The Mimic Men
    [10] => Mr Stone and the Knights Companion
    [11] => The Mystic Masseur
    [12] => The Suffrage of Elvira
    [13] => A Way in the World
)

我试过了:

$_books = array();
foreach($books as $book){
    if(substr($book, 0, 4) == "The "){
    $_books[substr($book, 4)] = $book;
    }
    else if(substr($book, 0, 3) == "An "){
    $_books[substr($book, 3)] = $book;
    }
    else if(substr($book, 0, 2) == "A "){
    $_books[substr($book, 2)] = $book;
    }
    else{
    $_books[$book] = $book;
    }
}
ksort($_books);
$books = array_values($_books);

但我知道这不是最好的解决方案,因为它有丢失值的风险(例如,如果输入中同时存在“A Fantasy”和“The Fantasy”,则输出中将只有“The Fantasy” )。那么,最好的解决方案是什么?

【问题讨论】:

  • 那么问题是你想要输出什么?两者都有?
  • 定义自己的排序函数,并检查单词的开头是否存在文章
  • @Tim 是的,我都想要。
  • Niet the Dark Absol 的回答对你来说应该很有趣。

标签: php arrays sorting


【解决方案1】:

使用自定义排序功能:

function handleArticles($str) {
    list($first,$rest) = explode(" ",$str." ",2);
       // the extra space is to prevent "undefined offset" notices
       // on single-word titles
    $validarticles = array("a","an","the");
    if( in_array(strtolower($first),$validarticles)) return $rest.", ".$first;
    return $str;
}
usort($books,function($a,$b) {
    return strnatcasecmp(handleArticles($a),handleArticles($b));
});

【讨论】:

  • 总结一下这里发生的事情:数组中的每个条目都经过重新组织,将首篇文章移到单词的末尾,用逗号分隔。例如:“A Way in the World”变成“Way in the World, A”。这个新字符串然后在自定义排序函数的不区分大小写的字符串比较中。
  • 此方法的一个不明显的好处是将文章连接到单词的末尾,因此它仍然用于排序,但是是次要的。考虑以下内容:“战争世界”,“战争世界”。删除“A”和“The”可能会导致它们被分类为“The World of War”、“A World of War”。但是,将文章连接到末尾可确保它们始终按“World of War, A”、“World of War, The”排序,从而导致“A World of War”、“The World of War”
  • This 抛出一些未定义的偏移错误。我错过了什么?
  • 啊,我明白了。它不喜欢单字标题。见编辑。
  • 对于任何感兴趣的人,请使用uasort 而不是usort 来维护索引关联。我有需要保留的非整数索引,这个简单的更改有助于在与上述代码的其余部分排序后保留它们。
【解决方案2】:

已编辑。 像这样使用自定义函数:

function customSort($a, $b) {
    $list = array(
        'The' => '',
        'A' => '',
    );
    $pattens = array();
    $replacement = array();
    foreach ($list as $from => $to){
        $from = '/\b' . $from . '\b/';
        $pattens[] = $from;
        $replacement[] = $to;
    }
     $a = preg_replace($pattens, $replacement, $a);
     $b = preg_replace($pattens, $replacement, $b);

     return strcmp($a,$b);
}
       $array = array("The Vendor", "The World of War", "A World of War");
       usort($array, 'customSort');

    print_r($array);

结果:

Array ( [0] => The Vendor [1] => A World of War [2] => The World of War ) 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-03-16
    • 1970-01-01
    • 1970-01-01
    • 2018-06-02
    • 1970-01-01
    • 2023-04-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多