0

让我先解释一下我的问题。我有一个简单的值对象Poi。为了简单起见,本示例中省略了私有属性和 getter/setter。

class Poi implements JsonSerializable
{
    public $latitude;
    public $longitude;
    public $category;

    public function __construct($category, $lat, $long)
    {
        $this->category = $category;
        $this->latitude = $lat;
        $this->longitude = $long;
    }

    public function jsonSerialize()
    {
        return array(
            'lat' => $this->latitude,
            'lng' => $this->longitude,
        );
    }
}

一些数据提供者负责返回一组 Poi。IE

class PoiProvider1
{
    public function getPois()
    {
        return array(
            new Poi('airport', 10, 10),
            new Poi('airport', 10, 15),
            new Poi('restaurant', 30, 30),
        )
    }
}

class PoiProvider2
{
    public function getPois()
    {
        return array(
            new Poi('hotel', 20, 20),
            new Poi('airport', 30, 30),
        )
    }
}

现在我想要一个结构如下的数组,我可以json_encode()

array(
    'airport' => array(
        new Poi('airport', 10, 10),
        new Poi('airport', 10, 15),
        new Poi('airport', 30, 30),
    ),
    'restaurant' => array(
        new Poi('restaurant', 30, 30),
    ),
    'hotel' => array(
        new Poi('hotel', 20, 20),
    )
);

在 json_encode 之后,最终会形成以下结构:

{
    "airport":[
        {"lat":10,"lng":10},
        {"lat":10,"lng":15},
        {"lat":30,"lng":30}
    ],
    "restaurant":[
        {"lat":30,"lng":30}
    ],
    "hotel":[
        {"lat":20,"lng":20}
    ]
}

我可以使用array_merge和一些数组复制来创建这样的结构,如下所示:

$provider1 = new PoiProvider1();
$provider2 = new PoiProvider2();
$pois = array_merge($provider1->getPois(), $provider2->getPois());
$poisNew = array();
foreach ($pois as $poi)
{
    $poisNew[$poi->category][] = $poi;
}

显然,在处理大量 poi 时,这会消耗内存并且速度很慢。必须有一些更好更快的方法(即使用迭代器),但我不知道如何解决这个问题。谁能给我一些指示如何进行?

4

1 回答 1

0

为了加快速度,消除后期处理。

消除后处理:

您可以为 pois 使用另一个全局或类静态容器,它会在构造过程中自动索引并存储它们,如下所示:

class Poi implements JsonSerializable {

public static $json;    // this is our new hero.

public $latitude;
public $longitude;
public $category;

public function __construct($category, $lat, $long){
    $this->category = $category;
    $this->latitude = $lat;
    $this->longitude = $long;
    array_push(self::$json[$category], $this); // this does the trick...
}

public function jsonSerialize()
{
    return array(
        'lat' => $this->latitude,
        'lng' => $this->longitude,
    );
}
}
Poi::$json = array();

现在在每次创建 poi 时,poi 实例都以您需要的形式存储到 Poi::$json 中。

生成 POI:

如果您不需要处理 poi,这也将简化您的提供程序:

class PoiProvider1 {

public function getPois(){      // no need to return if they are just for json.
   new Poi('airport', 10, 10);  // because each instance will be autoMagically 
   new Poi('airport', 10, 15);  // added to Poi::$json
   new Poi('restaurant', 30, 30);
}
}

但是,如果您在 poi 实例上执行其他操作,请不要使用上面的代码...

编码:

由于 $json 是一个关联数组,您可以通过使用获得所需的输出效果

json_encode((object)Poi::$json);

缺点是 poi 会留在内存中并在 gc 中存活,因为它们可以通过 Poi::$json 访问。所以在你设置 json_encode 之后

Poi::$json  = null;

我希望这有帮助。

于 2013-03-21T09:23:39.107 回答