2012-08-16 13 views
7

Chciałbym sortować ciągi w PHP, a dopasowanie powinno się odbywać przede wszystkim na pierwszych literach podciągu, a następnie na literach całego ciągu znaków.Sortuj ciągi znaków, najpierw pierwsze litery, potem litery wewnątrz słów

Na przykład, jeśli ktoś szuka do, a lista zawiera

Adolf 
Doe 
Done 

wynik powinien być

Doe 
Done 
Adolf 

Korzystanie regularne sort($array, SORT_STRING) czy takie rzeczy nie działa, Adolf jest sortowana przed inni.

Czy ktoś ma pomysł, jak to zrobić?

+1

nie można zrobić to proste wyszukiwanie. Sugeruję utworzenie wielu list dla każdej pozycji wystąpienia, której szukasz, a następnie posortuj te listy. – Tchoupi

+0

@ user1603166, twoje pytanie jest nieco niejednoznaczne. Z przykładu Romana, czy lista zawiera również "Drogomierz" i "Brzuch", jak należy go sortować? – Matthew

Odpowiedz

0

Można zamówić ciągi na podstawie stripos($str, $search), aby te z przodu (stripos() == 0) pojawiły się jako pierwsze.

Poniższy kod wypycha pozycje podciągu łańcucha wyszukiwania do oddzielnej tablicy, a następnie stosuje array_multisort(), aby zastosować odpowiednie porządkowanie do dopasowań; robienie tego w ten sposób, a nie usort() unika wielokrotnego dzwonienia pod numer 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

To sprytne rozwiązanie, ale zawiedzie, jeśli lista zawiera ciągi, które nie zawierają '$ search'. stripos() zwróci false, co jest utożsamiane z 0. (Łatwo wyprostowane, jeśli tablica zwraca ogromną liczbę zamiast fałszywej). – Matthew

+0

@Matthew Zakładam, że dopasowanie zostało już wykonane za pomocą grep lub sth :) –

+0

oczywiście, najlepiej powinno się to zrobić w tym samym stopniu, co ustalanie pozycji ;-) pozwól mi pomyśleć o tym. –

3

usort(array, callback) umożliwia sortowanie na podstawie zwrotnego.

przykład (coś takiego, nie spróbować)

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

Nie rozumiem twojej odpowiedzi. OK, proszę pozwolić mi sortować z własną funkcją, ale problem polega na tym, że funkcje sortowania dają mi Adolfa przed Doe w tym przypadku. – user1603166

+0

OK Spróbuję z tym, dzięki! – user1603166

+0

W zależności od tego, ile porównań dokonano w 'usort()', może to być dość ciężkie :) –

3

użyłbym niestandardową sortowania:

<?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); 

wyjściowa:

array(3) { 
    [0] => 
    string(3) "Doe" 
    [1] => 
    string(4) "Done" 
    [2] => 
    string(5) "Adolf" 
} 
+1

+1.Chociaż OP powinien mieć świadomość, że tutaj "Drogomierz" zostanie wymieniony przed 'Brzuchem', co może być pożądane lub nie. – Roman

+0

@Roman, myślę, że to jest punkt poszukiwań. Ale jeśli nie, usunięcie '$ diff' check i' return' spowoduje usunięcie tego zachowania. – Matthew

+0

Nie wiem, zakładam, że jest używana przez rodzaj funkcji "autouzupełniania", w tym przypadku wolałbym mieć wszystkie wyniki, które "nie zaczynają się od $ igły" posortowane alfabetycznie. – Roman

Powiązane problemy