适用于使用范围的表的数据结构

时间:2009-12-14 19:27:34

标签: php data-structures

我有一个看起来像这样的表:

       <22  23-27   
8-10   1.3   1.8
11-13  2.2   2.8
14-16  3.2   3.8

然后继续。所以我想查找这样的值:

lookup(11,25)

并获得响应,在本例中为2.8。用于此目的的最佳数据结构是什么?我有CSV格式的数据。

我希望用PHP编程。

谢谢。

6 个答案:

答案 0 :(得分:2)

我当然没有声称这是最好或最有效的数据结构,但这就是我将数据映射到一个非常类似于原始数据的二维PHP数组的方式:

$fp = fopen('data.csv', 'r');
$cols = fgetcsv($fp);
array_shift($cols); // remove empty first item
$data = array();
while ($row = fgetcsv($fp)) {
  list($min, $max) = explode('-', $row[0]);
  // TODO: Handle non-range values here (e.g. column header "<22")
  $data["$min-$max"] = array();
  for ($x = 0; $x < count($cols); $x++) {
    $data["$min-$max"][$cols[$x]] = $row[$x + 1];
  }
}

然后,您需要在lookup函数中添加一些解析逻辑:

function lookup($row, $col) {
  $return = null;
  // Loop through all rows
  foreach ($data as $row_name => $cols) {
    list($min, $max) = explode('-', $row_name);
    if ($min <= $row && $max >= $row) {
      // If row matches, loop through columns
      foreach ($cols as $col_name => $value) {
        // TODO: Add support for "<22"
        list($min, $max) = explode('-', $col_name);
        if ($min <= $col && $max >= $col) {
          $return = $value;
          break;
        }
      }
      break;
    }
  }
  return $return;
}

答案 1 :(得分:1)

某种二维数据结构怎么样?

X "coordinates" being <22, 23-27
Y "coordinates" being ...

二维数组可能会用于此目的。

然后你需要一些函数来将特定的X和Y值映射到范围,但这不应该太难。

答案 2 :(得分:1)

数据库结构:

values
------
value
x_range_start
x_range_end
y_range_start
y_range_end

代码:

function lookup(x, y) {
    sql = "
        SELECT * FROM values
        WHERE
            x >= x_range_start
            AND
            x <= x_range_end

            AND
            y >= y_range_start
            AND
            y <= y_range_end
    "

    /---/
}

您的数据将映射到数据库,如下所示:

      <22  23-27   
8-10   1.3   1.8
11-13  2.2   2.8
14-16  3.2   3.8

(value, x start, x end, y start, y end)
1.3, 0, 22, 8, 10
1.8, 23, 27, 8, 10
2.2, 0, 22, 11, 13
...

基本上存储表中每个值的x和y轴开始和结束编号。

答案 3 :(得分:0)

最简单的选项:创建数组数组,其中每个数组由5个元素组成:minX,maxX,minY,maxY,value,在你的情况下它将是

$data = array(
      array(8, 10, 0, 22, 1.3),
      array(8, 10, 23, 27, 1.8),
      array(11, 13, 0, 22, 2.2), etc

写一个遍历每个元素的循环并比较min&amp;参数的最大值:

 function find($x, $y) {
      foreach($data as $e) {
         if($x <= $e[0] && $x >= $e[1] && $y <= $e[2] && $y >= $e[3])
              return $e[4];
 }

使用小数据集,这将正常工作,如果您的数据集更大,您应该考虑使用数据库。

答案 4 :(得分:0)

我偏向于具有“哈希”功能的2维数组,该功能将范围映射到表格中的特定地址。

因此,您的基础数据结构将是一个二维数组:

    0     1   
0  1.3   1.8
1  2.2   2.8
2  3.2   3.8

然后你会写两个函数:

int xhash(int);
int yhash(int);

将原始参数转换为索引并将其转换为数组。所以xhash执行转换:

8-10    0
11-13   1
14-16   2

最后,您的查找操作变为。

function lookup($x, $y)
{
  $xIndex = xhash($x);
  $yIndex = yhash($y);
  // Handle invalid indices!

  return $data[$xIndex][$yIndex];
}

答案 5 :(得分:0)

嗯,其他答案都使用2D数组,这意味着使用2D循环来检索它。其中,如果你的范围是年龄范围或类似的东西,可能是有限的(只有这么多的年龄范围!),而不是一个问题(几百次迭代是什么?)。如果您的范围预计会扩展到庞大的数字,那么哈希地图上的游戏可能是您最好的选择。因此,您创建一个散列函数,将任何数字转换为相关范围,然后直接查找,而不是循环。它将是O(1)访问而不是O(n ^ 2)。

所以你的哈希函数可以是:function hash(n){if(n&lt; 22)return 1; if(n <25)返回2;返回-1;然后你可以用这些哈希值(1,2等)来指定你的范围,然后再去$ data [hash(11)] [hash(25)]