Sort array by object property in PHP?

前端 未结 15 884
萌比男神i
萌比男神i 2020-12-04 12:07

If I have an object as such:

class Person {
  var $age;
  function __construct($age) {
    $this->age = $age;
  }
}

and I have any array

相关标签:
15条回答
  • 2020-12-04 12:27

    You just need to write a custom comparison function, then use something like usort to do the actual sorting. For example, if the member variable was myVar, you could sort it as follows:

    function cmp($a, $b)
    {
        if ($a->myVar == $b->myVar) {
            return 0;
        }
        return ($a->myVar < $b->myVar) ? -1 : 1;
    }
    
    usort($myArray, "cmp");
    
    0 讨论(0)
  • Here is an option that takes following things into account:

    • namespaces
    • private properties
    • using getter and setter methods
    • property for sort as parameter

    PHP

    namespace Dummy;
    
    class Person {
    
        private $age;
    
        function __construct($age) {
            $this->setAge($age);
        }
    
        public function getAge()
        {
            return $this->age;
        }
    
        public function setAge($age)
        {
            $this->age = $age;
        }
    }
    
    class CustomSort{
    
        public $field = '';
    
        public function cmp($a, $b)
        {
            return strcmp($a->{'get'.ucfirst($this->field)}(), $b->{'get'.ucfirst($this->field)}());
        }
    
        public function sortObjectArrayByField($array, $field)
        {
            $this->field = $field;
            usort($array, array("Dummy\CustomSort", "cmp"));
            return $array;
        }
    }
    
    $robert = new Person(20);
    $peter = new Person(12);
    $robin = new Person(44);
    $people = array($robert, $peter, $robin);
    
    var_dump( $people );
    
    $customSort = new CustomSort();
    $people = $customSort->sortObjectArrayByField($people, 'age');
    
    var_dump( $people );
    
    0 讨论(0)
  • 2020-12-04 12:28

    You can do it with ouzo goodies:

    $result = Arrays::sort(array($person1, $person2), Comparator::compareBy('age'));
    

    http://ouzo.readthedocs.org/en/latest/utils/comparators.html

    0 讨论(0)
  • 2020-12-04 12:28

    If all member variables in question are guaranteed to be different, it will be simpler and faster to create a new collection indexed by these values and then ksort it:

     foreach($obj_list as $obj)
        $map[$obj->some_var] = $obj;
     ksort($map);
     /// $map now contains the sorted list
    

    If there are duplicate values, you can still avoid usort by utilizing a less known feature of sort that arrays of arrays are sorted by the value of the first scalar member.

     foreach($obj_list as $obj)
        $map[] = array($obj->some_var, $obj);
     sort($map); // sorts $map by the value of ->some_var
    

    I guess this still will be 10000000 times faster than usort

    0 讨论(0)
  • 2020-12-04 12:29

    You could either use usort or a heap.

     class SortPeopleByAge extends SplMaxHeap
      {
          function compare($person1, $person2)
          {
              return $person1->age - $person2->age;
          }
      }
    
      $people = array(new Person(30), new Person(22), new Person(40));  
      $sorter = new SortPeopleByAge;
      array_map(array($sorter, 'insert'), $people);
      print_r(iterator_to_array($sorter)); // people sorted from 40 to 22
    

    Note that the purpose of an Heap is to have an ordered collection at all times and not to replace usort. For large collections (1000+), a heap will be faster and less memory intensive though.

    An added benefit of having Heaps is being able to use their comparison function for callbacks to other sorting functions, like usort. You just have to remember that the order for the comparison is reversed, so any comparison done with a Heap will result in reversed order in usort.

    // using $people array and $sorter
    usort($people, array($sorter, 'compare'));
    print_r($people); // people sorted from 22 to 40
    

    usort is fine for small to medium collections where you will do the sorting once at the end. Of course, you dont have to have a heap to use usort. You can just as well add any other valid callback for the sorting.

    0 讨论(0)
  • 2020-12-04 12:29

    I went with the following approach: created a function that takes an array of objects, then inside the function I create an associative array using the property as key for the array, then sort they array keys using ksort:

    class Person {
        var $age;
        function __construct($age) {
          $this->age = $age;
        }
    }
    
    function sortPerson($persons = Array()){
        foreach($persons as $person){
            $sorted[$person->age] = $person;
        }
        ksort($sorted);
        return array_values($sorted);
    }
    
    $person1 = new Person(14);
    $person2 = new Person(5);
    
    $persons = array($person1, $person2);
    $person = sortPerson($persons);
    
    echo $person[0]->age."\n".$person[1]->age;
    /* Output:
    5
    14
    */
    
    0 讨论(0)
提交回复
热议问题