目前我正在遍历一个非常大的数据集。此多维数组需要按其子数组的特定数组值进行分组。由于这是一个假期项目,我想加深我的知识,并更多地使用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
中包含2
,86
,U3
或["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。
答案 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);