2009-03-23 17 views
1

現在、私はさまざまな位置のx座標とy座標を含む配列を持っています。PHPの配列のx座標とy座標を最も効率的に並べ替えますか?

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

これは、id 0の位置が(1,1)であることを示します。

時々、この配列をxで並べ替え、yで別の並べ替えを行いたいことがあります。

現在、私はデータをソートするためにarray-multisort()を使用していますが、このメソッドは効率的ではないと感じています。ソートを行うたびに、$ location配列をリニアに渡す必要があります。 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

、配列、あなたが持っているマルチソートを保つ前回のパスの必要性を排除するであろう次のようなものに構造を変える:

$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

あなたはマルチソートを使用して保存しておきたいです。

私は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); 
関連する問題