将子值指定为键的迭代器

时间:2013-12-29 03:06:01

标签: php arrays sorting iterator ogd-wien

目前我正在遍历一个非常大的数据集。此多维数组需要按其子数组的特定数组值进行分组。由于这是一个假期项目,我想加深我的知识,并更多地使用PHPs迭代器。重点是,我不知道如何使用关联键将数值多维数组转换为多维数组。

简短示例(GeoJSON to Array)

array (size=4)
  'type' => string 'FeatureCollection' (length=17)
  'features' => // THIS is the actual array
    array (size=207)
      0 => // Sub-Arrays like this one are repeating
        array (size=5)
          'type' => string 'Feature' (length=7)
          'geometry' => 
            array (size=2)
              'type' => string 'LineString' (length=10)
              'coordinates' => 
                array (size=410)
                  0 => 
                    array (size=2)
                      0 => float 16.359980888872
                      1 => float 48.208437070943
                  // etc.
      'geometry_name' => string 'SHAPE' (length=5)
      'properties' => 
        array (size=5)
          'OBJECTID'         => int 273
          // This/"LBEZEICHNUNG" is the part I want to order/summon
          // all further "geometry"-parts by
          'LBEZEICHNUNG'     => string '13A, 2, 86, U3' (length=1)
          'LTYP'             => string '1' (length=1)
          'LTYPTXT'          => string 'Tramway' (length=12)
          'SE_ANNO_CAD_DATA' => null
      'id' => int 1

features数组保存实际的循环数据集。 LBEZEICHNUNG是我想要排序/排序的值(单个或逗号分隔)。

举个例子:

// Original values:
'LBEZEICHNUNG' => string '13A, 2, 86, U3'

// Now split them and push the features into new keys that have those values:
'13A' => array(
  0 => // Sub-Arrays like this one are repeating
    array (size=5)
      'type' => string 'Feature' (length=7)
      'geometry' => 
        array (size=2)
          'type' => string 'LineString' (length=10)
          'coordinates' => 
            array (size=410)
              0 => 
                array (size=2)
                  0 => float 16.359980888872
                  1 => float 48.208437070943
              // etc.
  'geometry_name' => string 'SHAPE' (length=5)
  'properties' => 
    array (size=5)
      // "OBJECTID" now is obsolete
      // "LBEZEICHNUNG" is now obsolete
      'LTYP'             => string '1' (length=1)
      'LTYPTXT'          => string 'Tramway' (length=12)
      'SE_ANNO_CAD_DATA' => null
   // "id" now is obsolete as well
),
"2" => // gets the same values as "13A"
// same goes for "86" and "U3"

现在,13A中包含286U3["properties"]["LBEZEICHNUNG"]的每个子数组都会将其geometry推送到$data = new \RecursiveArrayIterator( $fileContents ); foreach( new \RecursiveIteratorIterator( $data ) as $key => $value ) { // foo. bar. dragons. } 已存在的子阵列/子迭代器的结束。

到目前为止,我只有一个基本的递归迭代器设置,它贯穿所有叶子。

RecursiveFilterIterator

重点是我无法弄清楚如何从迭代器中的值分配新键。我已经尝试使用{{1}}并且优雅地失败,因为它根本不打算这样做。坦率地说:我失败了​​,因为我找不到合适的迭代器,或者我对Iterators的了解还不够。

我得到了一个工作解决方案,嵌套的foreach-es推入另一个Array。因为这是我想要学习的假期项目,因此Iterator解决方案,我希望在长时间内更容易维护。

编辑: Link to the original Geo-JSON data set CC-BY-SA 3.0 / AUT - 维也纳市提供的数据。其他格式可以是found here

2 个答案:

答案 0 :(得分:1)

如果我理解正确,你想根据“LBEZEICHNUNG”键对数组进行排序/分组,并使用PHP迭代器。为此,您必须遍历整个数组,并构建一个包含按该键分组的值的新数组。这是简单的foreach逻辑。

当您想要遍历数据集并在遍历期间获取数据(或更改它)时,迭代器会闪烁。

在这种情况下,你是在迭代器(json_decode?)之外获取数据,这使得迭代器变得毫无意义 - 除非你需要做的不仅仅是排序。如果你这样做,我建议你以一种格式存储这些数据,这种格式允许你轻松地获取有序集合,比如数据库,然后你可以使用迭代器充分发挥潜力。


对路线进行分组的一种方法是使用基本的OOP:

class Route{
  protected $trams = array();
  // add other route properties (type, geometry etc.)

  public function assignTo(Tram $line){
   if(!in_array($line, $this->trams, true))
     $this->trams[] = $line;
  }

  public function getTrams(){
    return $this->trams;
  }
}

class Tram{
  public $name;
  protected $routes = array();

  public function __construct($name){
    $this->name= $name;
  }

  public function addRoute(Route $route){
    $this->routes[] = $route;
    $route->assignTo($this);
  }

  public function getRoutes(){
    return $this->routes;
  }
}

示例:

$trams = array();
foreach($data as $routeData){
  $route = new Route();
  $tramNames = explode(', ', $routeData['features']['properties']['LBEZEICHNUNG']);

  foreach($tramNames as $name){
    if(!isset($trams[$name]))
      $trams[$name] = new Tram($name);

    $trams[$name]->addRoute($route);
    // set other route properties...
  }    

}

答案 1 :(得分:0)

您可以使用usort根据子值对多维数组进行排序:

$JSON = iconv('UTF-8', 'UTF-8//IGNORE', utf8_encode(file_get_contents("http://data.wien.gv.at/daten/geoserver/ows?service=WFS&request=GetFeature&version=1.1.0&srsName=EPSG:4326&outputFormat=json&typeName=ogdwien:OEFFLINIENOGD")));
$geoarray = json_decode($JSON, true);
$myarray = $geoarray["features"];

function cmp($a, $b) {
        return $a["properties"]["LBEZEICHNUNG"] - $b["properties"]["LBEZEICHNUNG"];
}
usort($myarray, "cmp");

print_r($myarray);