2017-10-28 1 views
-3

지정된 getter의 반환 값으로 객체 배열을 정렬하는 방법은 무엇입니까?각 요소에 정의 된 getter를 사용하여 객체 배열을 정렬하는 방법은 무엇입니까?

예를 들어, 우리는 객체의 배열을 가지고 있습니다. 각 객체에는 DateTime 객체를 반환하는 'getCreatedAt'함수가 있습니다. 마지막 요소를 날짜별로 가져 오도록 배열을 정렬해야합니다.

+0

문제는 여기에 무엇입니까 .... 우리는 또한 테스트를 여기에두고

class Car { private $inputDate; public function getInputDate() : DateTime { return $this->inputDate; } } class CarPark { use ObjectManagement; private $cars; public function getLastCar() : Car { $result = $this->orderObjects($this->cars, 'getInputDate', 'DESC'); return current($result); } } 

이 이제 실체에 우리의 유스 케이스인가? – ccKep

+0

@ccKep 더 좋습니다. 고맙습니다. – Eloy

+0

무슨 뜻입니까? 질문을 게시하고 즉시 답변을 올렸습니까? – ccKep

답변

1

내부 개체 관리를위한 PHP 특성 인 솔루션에 도달했습니다. 이제 우리는 엔티티에서이 특성을 단순히 구현하여 개체 배열을 비교할 수 있습니다. 이것은 코드입니다.

trait ObjectManagement 
{ 
    private function orderObjects(array $objects, string $getter, string $ordering): array 
    { 
     usort(
      $objects, 
      [new ObjectAscDescOrderingByGetter($getter, $ordering), 'order'] 
     ); 

     return $objects; 
    } 

} 


class ObjectAscDescOrderingByGetter 
{ 

    private $getter; 
    private $ordering; 

    public function __construct(string $getter, string $ordering) 
    { 
     if (!in_array($ordering, ['ASC', 'DESC'])) { 
      throw new RuntimeException('Ordering type must be ASC or DESC.'); 
     } 

     $this->getter = $getter; 
     $this->ordering = $ordering; 
    } 

    public function order($objectA, $objectB) 
    { 
     $getter = $this->getter; 

     $comparisonValueA = $objectA->$getter(); 
     $comparisonValueB = $objectB->$getter(); 

     if ($comparisonValueA === $comparisonValueB) { 
      return 0; 
     } 

     if ($this->ordering == 'DESC') { 
      return ($comparisonValueA > $comparisonValueB) ? -1 : 1; 
     } else { 
      return ($comparisonValueA > $comparisonValueB) ? 1 : -1; 
     } 
    } 
} 

우리는 특성이 어떤 경우에 가장 좋은 방법은 아니라는 것을 알고 있지만,이 경우 우리는이 주문 기능은 정적으로 다른 클래스에서 구현 될 수있는 코드이기 때문에 매우 도움이되었다고합니다.

class ObjectManagementTestCase extends TestCase 
{ 

    use ObjectManagement; 

    /** 
    * @dataProvider getOrderingCases 
    * @param array $datesToOrder 
    * @param array $datesExpectedOrder 
    * @param string $ordering 
    */ 
    public function testOrdering(array $datesToOrder, array $datesExpectedOrder, string $ordering) 
    { 
     $objectsToOrder = []; 
     foreach ($datesToOrder as $dateToOrder) { 
      $objectsToOrder[] = $this->getOrderableMock($dateToOrder); 
     } 
     $objectsExpectedOrder = []; 
     foreach ($datesExpectedOrder as $expectedDateOrder) { 
      $objectsExpectedOrder[] = $this->getOrderableMock($expectedDateOrder); 
     } 

     $result = $this->orderObjects($objectsToOrder, 'getCreatedAt', $ordering); 
     $this->assertEquals($objectsExpectedOrder, $result); 
    } 

    public function getOrderingCases() 
    { 
     return [ 
      'Must order this in descendant manner.' => [ 
       ['2016-01-01', '2017-01-01', '2017-01-03', '2017-01-05'], 
       ['2017-01-05', '2017-01-03', '2017-01-01', '2016-01-01'], 
       'DESC' 
      ], 
      'Must order this in ascendant manner.' => [ 
       ['2016-01-01', '2017-01-03', '2017-01-01', '2017-01-05'], 
       ['2016-01-01', '2017-01-01', '2017-01-03', '2017-01-05'], 
       'ASC' 
      ], 
     ]; 
    } 

    private function getOrderableMock(string $date) 
    { 
     return new OrderableTestObject($date); 
    } 

    public function testThatInputArrayIsNotModified() 
    { 
     $objects = [ 
      $this->getOrderableMock('2016-01-01'), 
      $this->getOrderableMock('2017-01-03'), 
     ]; 

     $this->orderObjects($objects, 'getCreatedAt', 'DESC'); 

     $this->assertEquals(
      [ 
       $this->getOrderableMock('2016-01-01'), 
       $this->getOrderableMock('2017-01-03'), 
      ], 
      $objects 
     ); 

    } 

    public function testExceptionOnNotRecognizedOrder() 
    { 
     $this->expectException(RuntimeException::class); 
     $this->expectExceptionMessage('Ordering type must be ASC or DESC.'); 
     $this->orderObjects([], 'createdAt', ''); 
    } 
} 


class OrderableTestObject 
{ 
    private $createdAt; 

    public function __construct(string $date) 
    { 
     $this->createdAt = new DateTime($date); 
    } 

    public function getCreatedAt(): DateTime 
    { 
     return $this->createdAt; 
    } 
} 
관련 문제