我想在PHP中對字符串進行排序,匹配應該首先在子字符串的第一個字母上完成,然後在整個字符串的字母上完成。對字符串進行排序,第一個字母第一個,然後是字母內部的字母
例如,如果有人搜索do
,並且該列表包含
Adolf
Doe
Done
結果應該是
Doe
Done
Adolf
使用這樣的常規sort($array, SORT_STRING)
或東西不起作用,阿道夫之前排序其他。
有人有一個想法如何做到這一點?
我想在PHP中對字符串進行排序,匹配應該首先在子字符串的第一個字母上完成,然後在整個字符串的字母上完成。對字符串進行排序,第一個字母第一個,然後是字母內部的字母
例如,如果有人搜索do
,並且該列表包含
Adolf
Doe
Done
結果應該是
Doe
Done
Adolf
使用這樣的常規sort($array, SORT_STRING)
或東西不起作用,阿道夫之前排序其他。
有人有一個想法如何做到這一點?
您可以根據stripos($str, $search)
訂購字符串,以便前面的字符串(stripos() == 0
)首先出現。
以下代碼將搜索字符串的子串位置推入單獨的數組,然後使用array_multisort()
將適當的排序應用於匹配;這樣做而不是usort()
避免了多次撥打stripos()
。
$k = array_map(function($v) use ($search) {
return stripos($v, $search);
}, $matches);
// $k contains all the substring positions of the search string for all matches
array_multisort($k, SORT_NUMERIC, $matches, SORT_STRING);
// $matches is now sorted against the position
這是一個聰明的解決方案,但如果列表中包含不包含「$ search」的字符串,它將失敗。 stripos()將返回false,這等於0.(如果數組映射返回一個巨大的數字而不是false,則很容易糾正。) – Matthew 2012-08-16 13:06:07
@Matthew我假設匹配已經使用grep或sth :) – 2012-08-16 13:08:38
當然,理想情況下這應該與位置確定相同的步驟完成; - 讓我考慮一下。 – 2012-08-16 13:29:34
usort(array, callback)
讓你根據回調進行排序。
例如(這樣的事情,沒有嘗試)
usort($list, function($a, $b) {
$posa = strpos(tolower($a), 'do');
$posb = strpos(tolower($b), 'do');
if($posa != 0 && $posb != 0)return strcmp($a, $b);
if($posa == 0 && $posb == 0)return strcmp($a, $b);
if($posa == 0 && $posb != 0)return -1;
if($posa != 0 && $posb == 0)return 1;
});
我不明白你的答案。好的,我們讓我自己分類一個函數,但問題是在這種情況下排序函數在Doe之前給了我Adolf。 – user1603166 2012-08-16 12:49:54
好的,我會盡力而爲,謝謝! – user1603166 2012-08-16 12:53:44
取決於'usort()'內部進行了多少次比較,這可能會變得非常沉重:) – 2012-08-16 12:54:24
我會使用自定義排序:
<?php
$list = ['Adolf', 'Doe', 'Done'];
function searchFunc($needle)
{
return function ($a, $b) use ($needle)
{
$a_pos = stripos($a, $needle);
$b_pos = stripos($b, $needle);
# if needle is found in only one of the two strings, sort by that one
if ($a_pos === false && $b_pos !== false) return 1;
if ($a_pos !== false && $b_pos === false) return -1;
# if the positions differ, sort by the first one
$diff = $a_pos - $b_pos;
# alternatively: $diff = ($b_pos === 0) - ($a_pos === 0)
if ($diff) return $diff;
# else sort by natural case
return strcasecmp($a, $b);
};
}
usort($list, searchFunc('do'));
var_dump($list);
輸出:
array(3) {
[0] =>
string(3) "Doe"
[1] =>
string(4) "Done"
[2] =>
string(5) "Adolf"
}
你不能這樣做它用一個簡單的搜索。我建議你創建多個列表,對於你正在查找的事件的每個位置,然後對這些子列表進行排序。 – Tchoupi 2012-08-16 12:37:28
@ user1603166,你的問題有點含糊。從@羅曼的例子來看,如果列表中還包括「里程錶」和「腹部」,應該如何排序? – Matthew 2012-08-16 13:39:13