0

最初に私の問題を説明しましょう。私は単純な値 object を持っていますPoi。この例では、わかりやすくするために、プライベート プロパティとゲッター/セッターは省略されています。

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 の配列を返す責任があります。すなわち

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::$json 経由でアクセスできるため、poi がメモリに残り、gc に耐えられることです。json_encode を設定した後

Poi::$json  = null;

これが役立つことを願っています。

于 2013-03-21T09:23:39.107 に答える