0

I Have the following Array and I would like to sort it based on the $term = "geo" in relation only to [result_title] ?

Array
(
    [0] => Array
        (
            [result_title] => Agathoklis Georgiou
            [result_subtext] => Active Employee
        )

    [1] => Array
        (
            [result_title] => Frixos Georgiou
            [result_subtext] => Active Employee
        )

    [2] => Array
        (
            [result_title] => George Ellinas
            [result_subtext] => Active Employee
        )

    [3] => Array
        (
            [result_title] => Georgi Georgiev
            [result_subtext] => Active Employee
        )

    [4] => Array
        (
            [result_title] => Charalambos Georgiou
            [result_subtext] => Former Employee
        )

    [5] => Array
        (
            [result_title] => Georgia Kantouna
            [result_subtext] => Former Employee
        )
)

The desired result should be:

Array
(
    [0] => Array
        (
            [result_title] => George Ellinas
            [result_subtext] => Active Employee

        )

    [1] => Array
        (
            [result_title] => Georgi Georgiev
            [result_subtext] => Active Employee


        )

    [2] => Array
        (
            [result_title] => Georgia Kantouna
            [result_subtext] => Former Employee
        )

    [3] => Array
        (
            [result_title] => Agathoklis Georgiou
            [result_subtext] => Active Employee
        )

    [4] => Array
        (
            [result_title] => Charalambos Georgiou
            [result_subtext] => Former Employee
        )

    [5] => Array
        (
            [result_title] => Frixos Georgiou
            [result_subtext] => Active Employee
        )
)

I have tried various methods such as:

usort($data, function($a, $b) use ($term) {
    $x = strpos($a["result_title"], $term) === false;
    $y = strpos($b["result_title"], $term) === false;
    if ($x && !$y) return 1;
    if ($y && !$x) return -1;

    // use this if you want to sort alphabetically after the keyword sort:
    return strcmp($a["result_title"], $b["result_title"]);

    // or if you only want to sort by whether or not the keyword was found:
    return 0;
});

and

usort($data, function ($a, $b) use ($term) {
    similar_text($term, $a["result_title"], $percentA);
    similar_text($term, $b["result_title"], $percentB);

    return $percentA === $percentB ? 0 : ($percentA > $percentB ? -1 : 1);
});

and

usort($data, function ($a, $b) use ($term) {
    $levA = levenshtein($term, $a["result_title"]);
    $levB = levenshtein($term, $b["result_title"]);

    return $levA === $levB ? 0 : ($levA > $levB ? 1 : -1);
});

and

usort($data, function($a, $b){ return $a["result_title"] - $b["result_title"]; }); 

and many more without any proper result. Or maybe I cannot understand the method to achieve my result?

I have also checked: php sorting an array based on a string and How to sort an array by similarity in relation to an inputted word. but the answers are giving me the result I'm looking for.

jQuerybeast
  • 14,130
  • 38
  • 118
  • 196
  • 1
    can you provide your source array as PHP code? – Marcin Orlowski Nov 10 '18 at 22:16
  • @MarcinOrlowski you mean how the array is formed at first? – jQuerybeast Nov 10 '18 at 22:23
  • it does not matter where it comes from. Make it in valid PHP array so I can try w/o wasting time to convert this data into code myself :) – Marcin Orlowski Nov 10 '18 at 22:26
  • Array ( [0] => Array ( [result_title] => Agathoklis Georgiou [result_subtext] => Active Employee ) [1] => Array ( [result_title] => Frixos Georgiou [result_subtext] => Active Employee ) [2] => Array ( [result_title] => George Ellinas [result_subtext] => Active Employee ) [3] => Array ( [result_title] => Georgi Georgiev [result_subtext] => Active Employee ) [4] => Array ( [result_title] => Charalambos Georgiou [result_subtext] => Former Employee ) ) – jQuerybeast Nov 10 '18 at 22:28
  • @MarcinOrlowski I hope this is what you meant :S – jQuerybeast Nov 10 '18 at 22:29
  • @MarcinOrlowski Thank you however! – jQuerybeast Nov 10 '18 at 22:29
  • No. I meant PHP code, like `$a = [['result_title' => 'foo', 'result_subtext' => 'bar'], ....]` – Marcin Orlowski Nov 10 '18 at 22:45
  • @MarcinOrlowski Thanks for your effort. Nick's answer was just what I was looking for. – jQuerybeast Nov 10 '18 at 22:47

1 Answers1

1

Here's a function that I think will do what you want. I've presumed you want to find the value of $term at the beginning of a word. This code extracts any keyword in the title which includes $term and then sorts based on whether the keyword was found, followed by the ordering of the keyword, or if they are both the same, on the title.

$term = 'geo';
usort($data, function ($a, $b) use ($term) {
    // find the term in first entry
    $t1 = preg_match("/^.*?\b($term\w*)\b.*\$/i", $a['result_title'], $matches) ? $matches[1] : '';
    // find the term in second entry
    $t2 = preg_match("/^.*?\b($term\w*)\b.*\$/i", $b['result_title'], $matches) ? $matches[1] : '';
    // check if the terms were found
    if ($t1 == '' && $t2 != '') return 1;
    if ($t1 != '' && $t2 == '') return -1;
    // found in both - if not the same, just sort on the keyword
    if ($t1 != $t2) return strcmp($t1, $t2);
    // found the same keyword, sort on the whole title
    return strcmp($a['result_title'], $b['result_title']);
});

Since the output is long (it is what you asked for) I've omitted it but I've made a demo on 3v4l.org.

Nick
  • 138,499
  • 22
  • 57
  • 95
  • I dont know how to thank you enough. I've been trying so much the past 48 hours. Thank you! – jQuerybeast Nov 10 '18 at 22:46
  • Would it make a difference if I set the term string to lower? There is some confusions for example – jQuerybeast Nov 10 '18 at 22:50
  • @jQuerybeast I'm not sure what you mean by "set the term string to lower"? – Nick Nov 10 '18 at 23:06
  • @jQuerybeast I've made an edit to the answer to allow for the term being the whole word. – Nick Nov 10 '18 at 23:11
  • @jQuerybeast for your example you can't sort with a term of `1345` as it will automatically sort other values after that. You could sort with `$term='bill`;` https://3v4l.org/WDTYZ – Nick Nov 10 '18 at 23:12
  • what i mean by lowercase is that with the term "lia" i 1: [result_title] => ELIAS LIASSIS LTD and 2: [result_title] => Lia Markou. Shouldn't term "lia" bring up firstly [result_title] => Lia Markou? – jQuerybeast Nov 10 '18 at 23:14
  • 1
    @jQuerybeast the way the code works it won't sort that way because `'LIA' < 'Lia'`. If you want it to be case-insensitive change the `strcmp` to `strcasecmp` – Nick Nov 10 '18 at 23:18