最有效地在PHP中对数组中的x和y坐标进行排序?

时间:2009-03-23 00:15:38

标签: php optimization sorting

目前我有一个包含不同位置的x和y坐标的数组。

离。

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

这表示id 0的位置为(1,1)。

有时我想用x对这个数组进行排序,其他时候用y。

目前我正在使用array_multisort()对数据进行排序,但我觉得这种方法效率很低,因为每次排序之前,我必须通过$location数组进行线性传递才能构建索引(在x或y键上)我可以调用array_multisort()命令。

有谁知道更好的方法吗?即使存储这样的数据也许是一个坏主意?任何建议都会很棒。

4 个答案:

答案 0 :(得分: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 :(得分: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函数。完成后,您可以替换此代码

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

$s = array_pluck('x', $data2);

答案 2 :(得分: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);

答案 3 :(得分:-1)

保留你拥有的数组和多重排序,将结构更改为类似以下的内容将消除前一次传递的需要:

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

然后在所有列上使用array_multisort()。