2009-03-23 3 views
1

현재 다양한 위치의 x 및 y 좌표가 포함 된 배열이 있습니다.PHP의 배열에서 x와 y 좌표를 가장 효율적으로 정렬합니까?

ex. $ location [0] [ 'x'] = 1; $ location [0] [ 'y'] = 1

이것은 id 0의 위치가 (1,1)임을 나타냅니다.

간혹이 배열을 x로 정렬하고 다른 시간을 y로 정렬하려고합니다.

현재 array-multisort()를 사용하여 데이터를 정렬하고 있지만 정렬하기 전에는 항상이 방법이 비효율적이라고 생각합니다. $ 위치 배열을 통해 선형 패스를 만들어야합니다 (on x 또는 y 키)를 사용하여 array-multisort() 명령을 호출 할 수 있습니다.

누구든지 더 좋은 방법을 알고 있습니까? 아마도 이와 같은 데이터를 저장하는 것은 나쁜 생각입니까? 어떤 제안이라도 좋을 것입니다.

답변

2

usort()을 사용하면 배열 요소를 비교하는 방법을 선택할 수 있습니다.

// sort by 'y' 
usort($location, 'cmp_location_y'); 

// or sort by 'x' 
usort($location, 'cmp_location_x'); 

// here are the comparison functions 
function cmp_location_x($a, $b) { 
    return cmp_location($a, $b, 'x'); 
} 

function cmp_location_y($a, $b) { 
    return cmp_location($a, $b, 'y'); 
} 

function cmp_location($a, $b, $key) { 
    if ($a[$key] == $b[$key]) { 
     return 0; 
    } else if ($a[$key] < $b[$key]) { 
     return -1; 
    } else { 
     return 1; 
    } 
} 
-1

, 배열 및 당신이 가지고있는 multisort을 유지하는 이전의 패스에 대한 필요성을 제거 할 다음과 같은으로 구조를 변경 :

$locations = array( 
    'x' => $x_coordinates, 
    'y' => $y_coordinates, 
    'data' => $data_array 
); 

그럼 그냥 모든 컬럼에는 array_multisort()를 사용 .

+0

이 코드

foreach ($data2 as $temp) $s[] = $temp['x'];' 

를 대체 할 수있는 수행 한 후에는이 작업을 수행 할 경우 어떻게 x, y 및 데이터 사이의 관계를 유지합니까? –

+0

array_multisort는 관계를 보존합니다. 즉 위치 1의 x는 위치 1에 y를, 위치 1에는 데이터를 갖습니다. – OIS

+0

예, array_multisort()는 다른 배열에있는 항목 간의 관계를 보존합니다. –

0

jcinacio가 말한 것과 같습니다. 이 클래스를 사용하면 다른 차원의 위치뿐만 아니라 모든 종류의 데이터를 실제로 저장하고 정렬 할 수 있습니다. 필요에 따라 제거 등의 다른 메소드를 구현할 수 있습니다.

class Locations { 
    public $locations = array(); 
    public $data = array(); 
    public $dimensions = 2; 

    public function __construct($dimensions = null) 
    { 
     if (is_int($dimensions)) 
      $this->dimensions = $dimensions; 
    } 

    public function addLocation() 
    { 
     $t = func_num_args(); 

     if ($t !== $this->dimensions) 
      throw new Exception("This Locations object has {$this->dimensions} dimensions"); 

     $args = func_get_args(); 

     for ($i = 0; $i < $t; $i++) 
      $this->locations[$i][] = $args[$i]; 

     return $this; 
    } 

    public function sortByDimension($dimension = 1) 
    { 
     if ($dimension > $this->dimensions) 
      throw new Exception("Wrong number of dimensions"); 

     --$dimension; 

     $params[] = &$this->locations[$dimension]; 

     for ($i = 0, $t = $this->dimensions; $i < $t; $i++) { 
      if ($i === $dimension) 
       continue; 

      $params[] = &$this->locations[$i]; 
     } 

     call_user_func_array('array_multisort', $params); 

     return $this; 
    } 
} 

테스트 데이터 :

$loc = new Locations(3); 

$loc 
    ->addLocation(1, 1, 'A') 
    ->addLocation(2, 3, 'B') 
    ->addLocation(4, 2, 'C') 
    ->addLocation(3, 2, 'D') 
; 
$loc->sortByDimension(1); 
var_dump($loc->locations); 
$loc->sortByDimension(2); 
var_dump($loc->locations); 
+0

이 문제는 당신이 여전히 당신의 sortByDimensions에서 for 루프를 피할 수 없다는 것을 보여줍니다. 정렬 할 때마다 멀티 정렬을 호출하기 전에 색인을 작성해야합니다. –

+0

당신이 가지고있는 치수의 수와 얼마나 많은 위치에 상관없이 모든 치수의 수에 대한 상수가 그것의 루프입니다.속도가 느리고 느린 색인 루프와 달리 추가 할 위치는 많습니다. – OIS

+0

정렬 색인을 만드는 추가 비용은 일반적인 목적의 클래스의 이점에 비해 무시할 만합니다. – OIS

2

당신은 multisort를 계속 사용합니다.

나는 usort와 array_multisort의 빠른 벤치 마크를 만들었습니다. 심지어 색인을 작성하는 데만 10 멀티 스 트의 계산에서 usort보다 빠릅니다. 100 요소에서 약 5 배 빠릅니다. 약 1000 개의 요소에서 개선 된 수준으로 바로 빠릅니다. 사용자 함수 호출이 너무 느립니다. 실행 중입니다. 5.2.6

$count = 100; 

for ($i = 0; $i < $count; $i++) 
{ 
    $temp = array('x' => rand(), 'y' => rand()); 
    $data[] = $temp; 
    $data2[] = $temp; 
} 

function sortByX($a, $b) { return ($a['x'] > $b['x']); } 

$start = microtime(true); 
usort($data, "sortByX"); 
echo (microtime(true) - $start) * 1000000, "<br/>\n"; 

$start = microtime(true); 
foreach ($data2 as $temp) 
    $s[] = $temp['x']; 
array_multisort($s, SORT_NUMERIC, $data2); 
echo (microtime(true) - $start) * 1000000, "<br/>\n"; 

PHP에는 현재 ruby와 같은 array_pluck 기능이 없습니다. 당신이

$s = array_pluck('x', $data2); 
관련 문제