1

I need to sort a multidimensional array by a searched keyword. My array is like below.

<?php
array(
  array(
    'name'    => '11th-Physics',
    'branch'  => 'Plus One',
    'college' => 'Plus One',
  ),
  array(
    'name'    => 'JEE-IIT',
    'branch'  => 'Physics',
    'college' => 'IIT College',
  ),
  array(
    'name'    => 'Physics',
    'branch'  => 'Bsc Physics',
    'college' => 'College of Chemistry',
  ),
  array(
    'name'    => 'Chemical Engineering',
    'branch'  => 'Civil',
    'college' => 'Physics Training Center',
  ),
  array(
    'name'    => 'Physics Education',
    'branch'  => 'Mechanical',
    'college' => 'TBR',
  ),
)
?>

I need to sort this array when search keyword is physics . And after Sorting i need the result like below.

NEEDED RESULT

<?php
array(
  array(
    'name'    => 'Physics',
    'branch'  => 'Bsc Physics',
    'college' => 'College of Chemistry',
  ),
  array(
    'name'    => 'Physics Education',
    'branch'  => 'Mechanical',
    'college' => 'TBR',
  ),
  array(
    'name'    => '11th-Physics',
    'branch'  => 'Plus One',
    'college' => 'Plus One',
  ),
  array(
    'name'    => 'JEE-IIT',
    'branch'  => 'Physics',
    'college' => 'IIT College',
  ),
  array(
    'name'    => 'Chemical Engineering',
    'branch'  => 'Civil',
    'college' => 'Physics Training Center',
  ),
)

?>

That is I need to sort the array first by the name which is exactly like the searched keyword. Then wildcard search in name. Then to the next key branch and same as above. Is there any php function to sort this array like my requirement. I have already checked asort, usort. But I didn't get result properly.

AdhershMNair
  • 2,603
  • 2
  • 16
  • 30

2 Answers2

1

Just call this simple function I just created for your requirement, It works just fine :) change the priority order according to your need

function sortArray($array,$itemToSearch)
{
    $sortedArray = array();
    $priorityOrder = ['name','branch','college'];

    foreach ($priorityOrder as $key) 
    {
        foreach ($array as $i => $value) 
        {
            if(strpos(strtolower($value[$key]), strtolower($itemToSearch)) === 0)
            {
                array_push($sortedArray, $value);
                unset($array[$i]);
            }
        }
        foreach ($array as $i => $value) 
        {
            if(strpos(strtolower($value[$key]), strtolower($itemToSearch)) > 0)
            {
                array_push($sortedArray, $value);
                unset($array[$i]);
            }
        }
    }

    return $sortedArray;
}
Ananthakrishnan Baji
  • 1,006
  • 1
  • 6
  • 19
0

Here we go

So I started from the algorithm in this answer and modified it to fit your requirements. Since you have three different "priorities" to you sorting, we have to use some temporary variables to separate the elements we wish sorted.

// arrays used to separate each row based on the row where the word "Physics" is found
$searchName = array();
$searchBranch = array();
$searchCollege = array();

// arrays used later for array_multisort
$foundInName = array();
$foundInBranch = array();
$foundInCollege = array();

foreach ($var as $key => $row) {
    if(strpos(strtolower($row['name']), 'physics') !== false) {
        $searchName[$key]  = $row['name'];
        $foundInName[] = $row;
    }
    elseif(strpos(strtolower($row['branch']), 'physics') !== false) {
        $searchBranch[$key]  = $row['branch'];
        $foundInBranch[] = $row;
    }
    elseif(strpos(strtolower($row['college']), 'physics') !== false) {
        $searchCollege[$key]  = $row['college'];
        $foundInCollege[] = $row;
    }
}

// Note: I use SORT_NATURAL here so that "11-XXXXX" comes after "2-XXXXX"
array_multisort($searchName, SORT_NATURAL, $foundInName);      // sort the three arrays separately
array_multisort($searchBranch, SORT_NATURAL, $foundInBranch);
array_multisort($searchCollege, SORT_NATURAL, $foundInCollege);

$sortedArray = array_merge($foundInName, $foundInBranch, $foundInCollege);

Outputting $sortedArray using var_dump() gives something like:

array(5) {
    [0]=> array(3) {
        ["name"]=> string(12) "11th-Physics"
        ["branch"]=> string(8) "Plus One"
        ["college"]=> string(8) "Plus One"
    }
    [1]=> array(3) {
        ["name"]=> string(7) "Physics"
        ["branch"]=> string(11) "Bsc Physics"
        ["college"]=> string(20) "College of Chemistry"
    }
    [2]=> array(3) {
        ["name"]=> string(17) "Physics Education"
        ["branch"]=> string(10) "Mechanical"
        ["college"]=> string(3) "TBR"
    }
    [3]=> array(3) {
        ["name"]=> string(7) "JEE-IIT"
        ["branch"]=> string(7) "Physics"
        ["college"]=> string(11) "IIT College"
    }
    [4]=> array(3) {
        ["name"]=> string(20) "Chemical Engineering"
        ["branch"]=> string(5) "Civil"
        ["college"]=> string(23) "Physics Training Center"
  }
}

As you can see 11th-Physics comes out first. That is because the ASCII value of numbers is lower than that of letters. To fix this, modify the $search... arrays by prepending a high ASCII character before the string.

if(strpos(strtolower($row['name']), 'physics') !== false) {
    // if the first character is a number, prepend an underscore
    $searchName[$key]  = is_numeric(substr($row['name'], 0, 1)) ? '_'.$row['name'] : $row['name'];
    $foundInName[] = $row;
}

Which yields the following output:

array(5) {
    [0]=> array(3) {
        ["name"]=> string(7) "Physics"
        ["branch"]=> string(11) "Bsc Physics"
        ["college"]=> string(20) "College of Chemistry"
    }
    [1]=> array(3) {
        ["name"]=> string(17) "Physics Education"
        ["branch"]=> string(10) "Mechanical"
        ["college"]=> string(3) "TBR"
    }
    [2]=> array(3) {
        ["name"]=> string(12) "11th-Physics"
        ["branch"]=> string(8) "Plus One"
        ["college"]=> string(8) "Plus One"
    }
    [3]=> array(3) {
        ["name"]=> string(7) "JEE-IIT"
        ["branch"]=> string(7) "Physics"
        ["college"]=> string(11) "IIT College"
    }
    [4]=> array(3) {
        ["name"]=> string(20) "Chemical Engineering"
        ["branch"]=> string(5) "Civil"
        ["college"]=> string(23) "Physics Training Center"
    }
}

Try it here!

William Perron
  • 1,050
  • 13
  • 17