Bu kodlama daha verimli bir yolu var mı?

4 Cevap php

Söz konusu kod 2. foreach döngüsü içinde bulunan kodu, amacı tam yinelenen enlem ve boylamları önlemektir.

foreach($aUsers as $k => $v)
{
    // generate address
    $aAddress = array();
    if(!empty($v['city_location']))
        $aAddress[] = $v['city_location'];
    if(!empty($v['country_child_id']))
    {
        $aRow = $oDb->select('name')
             ->from(getT('country_child'))
             ->where('child_id = \''.$v['country_child_id'].'\'')
             ->execute('getRow');
        $aAddress[] = $aRow['name'];
    }
    if(!empty($v['postal_code']))
        $aAddress[] = $v['postal_code'];
    if(!empty($v['country_iso']))
    {
        $aRow = $oDb->select('name')
             ->from(getT('country'))
             ->where('country_iso = \''.$v['country_iso'].'\'')
             ->execute('getRow');
        $aAddress[] = $aRow['name'];
    }
    $sAddress = implode(', ',$aAddress);
    /// get location
    $aLatLon = $oGeoMap->getLatLon($v['user_id'],1,$sAddress);
    if($aLatLon['success'] === true)
    {
        foreach($aUsers as $k2 => $v2)
        {
            $iAdd = .01;
            $iAttempts = 0;
            while($v2['latitude'] == $aLatLon['latitude'] && $v2['longitude'] == $aLatLon['longitude'])
            {
                $iAttempts++;
                switch($iAttempts){
                    case 1:
                        $aLatLon['latitude'] += $iAdd;
                        break;
                    case 2:
                        $aLatLon['longitude'] += $iAdd;
                        break;
                    case 3:
                        $aLatLon['latitude'] += $iAdd;
                        $aLatLon['longitude'] += $iAdd;
                        break;
                    case 4:
                        $aLatLon['latitude'] -= $iAdd;
                        $aLatLon['longitude'] -= $iAdd;
                        break;
                    case 5:
                        $aLatLon['latitude'] += $iAdd;
                        $aLatLon['longitude'] -= $iAdd;
                        break;
                    case 6:
                        $aLatLon['latitude'] -= $iAdd;
                        $aLatLon['longitude'] += $iAdd;
                        break;
                    case 7:
                        $iAdd += .01;
                        $iAttempts = 0;
                        break;
                }
            }
        }
        $aUsers[$k]['latitude'] = $aLatLon['latitude'];
        $aUsers[$k]['longitude'] = $aLatLon['longitude'];
        $aUsers[$k]['address'] = $sAddress;
    }
    else
        unset($aUsers[$k]);
}

4 Cevap

Ben kuvvetle Frank Farmer yorumuna katılıyorum, ama işler bu satırlar boyunca bir şey denemek yapmanın bu şekilde ısrar ederseniz:

$lls = array();
static $offs = array( array(1,0), array(0,1), array(1,1),
    array(-1,-1), array(1,-1), array(-1,1) );

foreach($aUsers as $k=>&$v) {
    $lla=$la=somelat; $llo=$lo=somelong;
    for($add=.01;isset($lls["{$lla}x$llo"]);$add+=.01) {
        foreach($offs as $o) {
            $lla=$la+$o[0]*$add; $llo=$lo+$o[1]*$add;
            if(!isset($lls["{$lla}x$llo"])) break;
        }
    }
    $lls["{$lla}x$llo"] = true;
    $v['latitiude']=$lla; $v['longtitude']=$llo;
    $v['address'] = $sAddress;
}

Ben doğru niyetini anlamak Yani, eğer. Ve standartlarına kendinizi uymak için değişken isimlerini değiştirmek ;-)

Kod denenmemiştir.

Ve hayır, ben yeniden okumak tam kod gitmiyorum ;-)

Varolan enlem + boylam pozisyonları tutan ikinci bir veri yapısı, örneğin kullanarak deneyebilirsiniz sonra enlem boylam tarafından dizine bir kullanıcı 2-D dizisi. Aksine $aUsers dizi üzerinde döngü yerine, belirli bir enlem ve boylam bu diğer veri yapısı içinde var olup olmadığını kontrol edin.

Sadece dizi anahtarları olarak tamsayılar ve dizeleri kullanabilir ve tamsayılar ya da dizeleri ya kayan nokta sayıları hassas döküm kaybına neden olacak gibi enlem kullanıyorsanız ve eğer, onların bit dize eşdeğerleri kayan nokta numaraları dönüştürmek gerektiğini unutmayın boylam tuşları gibi. Basit bir pack('d', $l) çalışması gerekir, ya da kullanabilirsiniz:

function fl2hex($l, $fmt='d') {
    $hex = unpack('H*', pack($fmt, $l));
    return $hex[1];
}

(Ben PHP sadece double kullanır eminim olsa) sizin enlem ve boylam yüzer değil çiftler olarak depolanır biliyorsanız, yerine 'd' den paket biçimi olarak 'f' kullanabilirsiniz.

Okunabilmesi için, size kod parçalarını Refactor (örneğin switch($iAttempts)) gibi ek fonksiyonlar olabilir.

Tek bir yerde birden fazla kişi sorunu için olduğu gibi, (harita basılı yerine, bir ekranda görüntülenir varsayılarak) bir çözeltisi bir grup insan için farklı bir gösterge kullanmaktır. Bir kullanıcı grubu simgesinin üzerine mouse zaman (ki mantıklı eğer), bu insanların konumu simgeyi bağlayan bir çizgi ile, bireysel simgeleri bir yıldız haline her "patlayabilir" olabilir. Birkaç uygulamalarında benzer bir şey gördüm, ama şu anda hangilerinin düşünemiyorum.

Sen bir noktalı virgül ile anahtarı () kullanabilirsiniz ... Ör

switch($attempts) {
    case 1;
    case 3;
    case 5;
        $aLatLon['latitude'] += $iAdd;
    break;
}

Bu test değil; ama bu veya benzer bir şey gibi devam edersen, bu iş olacak eminim.

Umarım bu yardımcı

Suggestion:

Bu, tüm kod için genel bir öneri değil, sadece iç döngü daha fazladır. Ben özel yapılar yerine diziler kullanmak kodunu değiştirmek istiyorsunuz. Burada temel bir örnek:

foreach($aUsers as $k => $v)
{
    $userInfo = new UserInfo($v);

    // generate address
    $sAddress = $userInfo->getAddress();

    /// get location
    $latLonResult = $oGeoMap->getLatLon($userInfo->user_id, 1, $sAddress);
    ...
}

Actual answer:

Bildiğim kadarıyla iç döngü optimize gibi, isterim sadece delete that code. Aynı yerde birden fazla kullanıcıya sahip yeni bir UI öğesi ile gelip, ya da onların lat / uzun zaten haritaya eklenmiş bir kullanıcıyı görmezden ya.

Onu tutmak gerekir, Michael'ın çözüm iyi görünüyordu.