PHP nesnelerin bir dizi sıralamak nasıl?

3 Cevap php

Ben bir grup insan var demek, bu gibi kodlanmış bir isim, cinsiyet ve yaş özelliğine sahip her kişi:

public class Person
{
   private $name, $sex, $age;
   public function Person ($name, $sex, $age)
   {
       $this->name = $name;
       $this->sex = $sex;
       $this->age = $age;
   }
   public function getName();    
   public function getSex();
   public function getAge();
}

public class People
{
   private $people = array();
   public function addPerson ($name, $sex, $age)
   {
      $this->people[] = new Person($name, $sex, $age);
   }
}

Nasıl People sınıfına insanların isimleri artan sırayla $people dizi kriteri sortPeople() bir yöntem uygulamak?

3 Cevap

Here is a working code with a static method. It also uses the fact that the static method can access private ivars :) It also uses PHP awesome reflexivity <3.

Bu kod hakkında iyi bir nokta Person bakış bir cepten noktasında daha iyi sıralama yöntemi sağlamak için sınıf olmasıdır. Sadece sınıf Person Diğer Person sıralamak için nasıl biri olmalıdır. Ne People veya başka indepent işlev gerekir.

Not: parametresi bir işlev olarak adlandırılan olabilir eğer sadece doğrular gibi, is_callable() kullanarak değil, ancak mevcut görünürlük ile aslında çağrılabilir olmadığını kontrol etmez (kamu, özel, korumalı)

class Person
{
    private $name, $sex, $age;
    public function Person($name, $sex, $age)
    {
        $this->name = $name;
        $this->sex = $sex;
        $this->age = $age;
    }

    public static function sortByName(Person $p1, Person $p2)
    {
        return strcmp($p1->name, $p2->name);
    }

    public static function sortByAge(Person $p1, Person $p2)
    {
        return ($p1->age - $p2->age);
    }
}

class People
{
    private $people = array();
    public function addPerson($name, $sex, $age)
    {
        $this->people[] = new Person($name, $sex, $age);
    }

    public function display()
    {
        print_r($this->people);
    }

    public function sort($attribute = 'name')
    {
        $sortFct = 'sortBy' . ucfirst(strtolower($attribute));
        if (!in_array($sortFct, get_class_methods('Person')))
        {
            throw new Exception('People->sort(): Can\'t sort by ' . $attribute);
        }
        usort($this->people, 'Person::' . $sortFct);
    }
}

$people = new People;
$people->addPerson('Steve', 'M', 31);
$people->addPerson('John', 'M', 24);
$people->addPerson('Jane', 'F', 26);
$people->addPerson('Sally', 'F', 21);
$people->display();
$people->sort();
$people->display();
$people->sort('age');
$people->display();

usort bir göz atın. Bu, kendi karşılaştırma işlevi belirlemenizi sağlar. Iki nesne karşılaştırıldığında gerekir her zaman, bu (eşit iseler ya da) bir diğerinden daha büyük olduğunu görmek için belirtmek karşılaştırma işlevi arayacak. Karşılaştırma fonksiyonu Eğer onları karşılaştırmak için iki Person nesneleri alanlarla için ne gerekiyorsa yapabilirim.

(Sizin örnekte olduğu gibi) sınıf yöntemleri ile geri çağrıları yaparken, passing callbacks bakmak. Örneğin, böyle bir şey yapabilirsiniz:

class People {
    // your previously defined stuff here...

    public function sort() {
        usort($this->people, array($this, 'comparePeople'));
    }

    public function comparePeople(Person $p1, Person $p2) {
        return strcmp($p1->getName(), $p2->getName());
    }
}

Siz de tabii Person sınıfına getName() eklemeniz gerekir.

Statik bir yaklaşım, böyle bir şey olabilir:

function sortPeople($people) {
    usort($people, array('People', 'comparePeople'));
}

class People {
    // your previously defined stuff here...

    public static function comparePeople(Person $p1, Person $p2) {
        return strcmp($p1->getName(), $p2->getName());
    }
}

Gördüğünüz gibi, çok benzer. Ben statik yaklaşımı kullanmanızı tavsiye etmem. Mesier ve tek sorumluluk ilkesini ihlal ediyor.

GetName () zaman alıcı bir işlemdir Özellikle eğer decorate-sort-undecorate desen kullanarak daha iyi olabilir.

<?php

class Person {
    private $name;
    function getName() {
      return $this->name;
    }
    function __construct($name) {
      $this->name = $name;
    }
}

$people = array(
    new Person('Jim'),
    new Person('Tom'),
    new Person('Tim'),
    new Person('Adam')
);

// actual sorting below
$people = array_map(create_function('$a', 'return array($a->getName(), $a);'), $people); // transform array of objects into array of arrays consisted of sort key and object
sort($people); // sort array of arrays
$people = array_map('end', $people); // take only last element from each array

print_r($people);

How does it work?

Bunun yerine ilk son eleman nesne dizileri dizi sıralamak nesneler dizisi sıralama ve sıralamak istediğiniz hangi anahtarıdır. Sıralama sonra sadece nesneyi tutmak.

PHP birer unsurları tek karşılaştırarak iki aynı uzunlukta diziyi karşılaştırır çünkü diziler dizi sıralama için sadece sort kullanabilirsiniz.

Sorting by multiple fields

Sen soyadına göre sıralama, örneğin, bir sıralama anahtarı daha sonra kullanmak ve soyadları aynıdır eğer dikkate ilk adını alabilir. Öyle gibi önem sırasına ile birden tuşları ile dekorasyon yapabilirsiniz:

$people = array_map(create_function('$a', 'return array($a->getSurname(), $a->getName(), $a);'), $people);

Why it's fast

Bu şekilde daha hızlı olabilir o n uzunluğunda dizi sıralama için sadece n-kez () getName çağrıları için usort kullanarak. Karşılaştırmalar sırasında sıralama karşılaştırıcıda inşa kadar hızlı olmalıdır kullanılarak yapılır. In usort yöntemi özel karşılaştırma sıralama sırasında birden çok kez (daha fazla n kere) denir ve bu yüzden bazı şeyleri yavaşlatabilir.