Search code examples
phpperformancenaming-conventionstheory

Is there a more efficient way of coding this?


The code in question is the code contained within the 2nd foreach loop, the purpose of which is to prevent exact duplicate latitude and longitudes.

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]);
}

Solution

  • I strongly agree with Frank Farmer's comment, but if you insist on this way of doing things try something along these lines:

    $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;
    }
    

    That is, if I understand your intention correctly. And change variable names to adhere to your standards yourself ;-)

    Code is untested.

    And no, I'm not going to re-read the full code ;-)