“附近的人”功能实现


核心思想:

1.以当前登录用户为中心,向四个方向获取最近用户

2.汇总查询出的用户,计算当前用户与这些用户的精确距离

3.按最短距离排序


图例:


数据表sql:

CREATE TABLE IF NOT EXISTS `location` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `x` decimal(10,0) NOT NULL,
  `y` decimal(10,0) NOT NULL,
  `user` varchar(200) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;


程序1:创建n个用户

<?php
$values = array();

for ($i=0; $i<500; $i++)
{
	$x = rand(1, 1000);
	$y = rand(1, 1000);
	
	$values [] = "({$x}, {$y}, 'user_{$i}')" ;
}
$sql = 'insert into location(`x`, `y`, `user`) values'.implode(',', $values) ;

$db = new PDO('mysql:host=localhost;dbname=test', 'root', 'lixinxin') ;
$db->query('set names utf8');

$flag = $db->exec($sql);

if($flag > 0){
	printf("insert ok \n");
}

?>


程序2:获取附近的人

<?php
/**
 * 获取附近的人(8名)
 */

$my_x = 200;
$my_y = 100;

$ulist = array();

$limit = 8;

$db = new PDO('mysql:host=localhost;dbname=test', 'root', 'lixinxin') ;
$db->query('set names utf8');

$sqls[] = "select * from location where x>$my_x and y>$my_y order by x asc,y asc limit 8" ;	//右上方向 x++ y++
$sqls[] = "select * from location where x>$my_x and y<$my_y order by x asc,y desc limit 8" ;	//右下方向 x++ y--
$sqls[] = "select * from location where x<$my_x and y>$my_y order by x desc,y asc limit 8" ;	//左上方向 x-- y++
$sqls[] = "select * from location where x<$my_x and y<$my_y order by x desc,y desc limit 8" ;	//左下方向 x-- y--

foreach ($sqls as $sql)
{
	$query = $db->query($sql);
	if ($query)
	{
		$data = $query->fetchAll(PDO::FETCH_ASSOC);
		if (is_array($data)){
			$ulist = array_merge($ulist, $data);
		}
	}
}

foreach ($ulist as $_key => $_val)
{
	$ulist[$_key]['distance'] = getDistance($my_x, $my_y, $_val['x'], $_val['y']);
}

usort($ulist, function($m, $n){
	if ($m['distance'] == $n['distance'])	return 0;
	if ($m['distance'] > $n['distance'])	return 1;
	return -1;
}) ;

$ulist = array_splice($ulist, 0, 8); // limit 8

file_put_contents('./log.txt', var_export($ulist, true)); // debug

function getDistance($x1, $y1, $x2, $y2)
{
	$line_a = abs($x1-$x2);
	$line_b = abs($y1-$y2);
	
	// C^2 = A^2 + B^2
	
	$line_c = pow(pow($line_a, 2) + pow($line_b, 2), 1/2);
	
	return intval($line_c);
}

?>






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值