自定义对平面数组进行排序,优先考虑以输入字符串开头的值

问题描述 投票:0回答:6

我有数组并包含 50 个值,

示例

[
    'london',
    'bluehit',
    'green',
    'lonpark',
    'abc',
    'aab',
    'lonsee',
]

我想优先对以提供的字符串开头的值进行排序,然后按传统的字母顺序排序。

如果我给出一个参数为

lon
那么我的数组应该排序为:

[
    'london',
    'lonpark',
    'lonsee',
    'aab',
    'abc',
    'blurhit',
    'green',
]
php arrays sorting prefix custom-sort
6个回答
2
投票
  1. 将有问题的字符串替换为代码为 1 的字符
  2. 正常排序
  3. 将角色替换回来

就是这样 ;)

 $str = "lon";
 $a = array('london', 'bluehit', 'green', 'lonpark', 'abc', 'aab', 'lonsee');
 $b = preg_replace("~^$str~", "\x01", $a);
 sort($b);
 $b = preg_replace('~\x01~', "lon", $b);
 print_r($b);

upd:更简单的是在字符串中预先添加“\x01”而不是替换它。这还允许不区分大小写的匹配或匹配一组字符串:

$str = "lon"; $a = array('london', 'bluehit', 'green', 'Lonpark', 'abc', 'aab', 'lonsee'); $b = preg_replace("~^$str~i", "\x01$0", $a); sort($b); $b = str_replace('~\x01~', "", $b); print_r($b);
    

2
投票
正如其他人所说,

usort

和定制比较器非常合适。这是一个具有工厂函数(在本例中为返回函数的函数)的示例,该函数根据所需的前缀生成比较器(使用
closures)。

$subject = explode(',', 'london,bluehit,green,lonpark,abc,aab,lonsee'); function make_comparator($prefix) { return function ($a, $b) use ($prefix) { if (strpos($a, $prefix) === 0 && strpos($b, $prefix) !== 0) { // $a starts with $prefix (and $b does not), sift up return -1; } elseif (strpos($a, $prefix) !== 0 && strpos($b, $prefix) === 0) { // $b starts with $prefix (and $a does not), sift down return 1; } else { // Otherwise, do a normal string comparison return strcmp($a, $b); } }; } $sorted = $subject; usort($sorted, make_comparator('lon')); var_dump($sorted);

对于低于 5.3.0 的 PHP 版本(上述要求),您可以执行类似的操作:

function prefix_comparator($a, $b, $prefix) { if (strpos($a, $prefix) === 0 && strpos($b, $prefix) !== 0) { // $a starts with $prefix (and $b does not), sift up return -1; } elseif (strpos($a, $prefix) !== 0 && strpos($b, $prefix) === 0) { // $b starts with $prefix (and $a does not), sift down return 1; } else { // Otherwise, do a normal string comparison return strcmp($a, $b); } } $sort_by_lon = create_function('$a, $b', 'return prefix_comparator($a, $b, "lon");'); $sorted = $subject; usort($sorted, $sort_by_lon); var_dump($sorted);

(行话抱歉)


1
投票
这个问题被很多人问到。看一下使用自定义排序功能。来自 php.net:

uksortusort



0
投票
这是版本的另一种可能性。 5.3+:

function pref_sort($arr, $pref, $case_insensitive = true) { $case_insensitive ? natcasesort($arr) : sort($arr); $pref_arr = array_filter($arr, function($val) use ($pref){ return (strpos(strtolower($val), strtolower($pref)) === 0); }); return array_values($pref_arr + array_diff($arr, $pref_arr)); }

用途:

$pref_str = 'lon'; $array = array('green', 'Lonpark', 'london', 'bluehit', 'abc', 'aab', 'lonsee', 'lon', 'Lon', 'Aab'); // Case-insensitive: $sorted_array = pref_sort($array, $pref_str); print_r($sorted_array); /** Array ( [0] => lon [1] => Lon [2] => london [3] => Lonpark [4] => lonsee [5] => Aab [6] => aab [7] => abc [8] => bluehit [9] => green ) **/ // Case-sensitive: $sorted_array = pref_sort($array, $pref_str, false); print_r($sorted_array); /** Array ( [0] => Lon [1] => Lonpark [2] => lon [3] => london [4] => lonsee [5] => Aab [6] => aab [7] => abc [8] => bluehit [9] => green ) **/
    

0
投票
要执行最少的函数调用,请使用

array_multisort()

循环一次以填充布尔值数组,指示是否在每个字符串的开头找到针字符串。当按升序对布尔值进行排序时,

false

 位于 
true
 之前。

然后通过比较整个字符串来打破平局。

代码:(

演示

$startsWith = 'lon'; array_multisort( array_map( fn($w) => !str_starts_with($w, $startsWith), $array ), $array ); var_export($array);
    
© www.soinside.com 2019 - 2024. All rights reserved.