2012-08-16 190 views
7

我想在PHP中對字符串進行排序,匹配應該首先在子字符串的第一個字母上完成,然後在整個字符串的字母上完成。對字符串進行排序,第一個字母第一個,然後是字母內部的字母

例如,如果有人搜索do,並且該列表包含

Adolf 
Doe 
Done 

結果應該是

Doe 
Done 
Adolf 

使用這樣的常規sort($array, SORT_STRING)或東西不起作用,阿道夫之前排序其他。

有人有一個想法如何做到這一點?

+1

你不能這樣做它用一個簡單的搜索。我建議你創建多個列表,對於你正在查找的事件的每個位置,然後對這些子列表進行排序。 – Tchoupi 2012-08-16 12:37:28

+0

@ user1603166,你的問題有點含糊。從@羅曼的例子來看,如果列表中還包括「里程錶」和「腹部」,應該如何排序? – Matthew 2012-08-16 13:39:13

回答

0

您可以根據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 
+0

這是一個聰明的解決方案,但如果列表中包含不包含「$ search」的字符串,它將失敗。 stripos()將返回false,這等於0.(如果數組映射返回一個巨大的數字而不是false,則很容易糾正。) – Matthew 2012-08-16 13:06:07

+0

@Matthew我假設匹配已經使用grep或sth :) – 2012-08-16 13:08:38

+0

當然,理想情況下這應該與位置確定相同的步驟完成; - 讓我考慮一下。 – 2012-08-16 13:29:34

3

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; 
}); 
+0

我不明白你的答案。好的,我們讓我自己分類一個函數,但問題是在這種情況下排序函數在Doe之前給了我Adolf。 – user1603166 2012-08-16 12:49:54

+0

好的,我會盡力而爲,謝謝! – user1603166 2012-08-16 12:53:44

+0

取決於'usort()'內部進行了多少次比較,這可能會變得非常沉重:) – 2012-08-16 12:54:24

3

我會使用自定義排序:

<?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" 
} 
+1

+1。雖然OP應該知道,這裏'里程錶'將在'腹部'之前列出,這可能或不可取。 – Roman 2012-08-16 13:05:02

+0

@羅曼,我認爲這是搜索的重點。但是,如果不是,刪除'$ diff'檢查和'return'將刪除該行爲。 – Matthew 2012-08-16 13:06:59

+0

不知道,我認爲它被某種「自動完成」功能所使用,在這種情況下,我寧願讓所有'不以$字母開頭'的結果按字母排序。 – Roman 2012-08-16 13:11:05

相關問題