在 perl 中,确保我的散列仅包含相距超过 30 英尺的 lat/lon
In perl ensure my hash only contains lat/lon that are more than 30 ft apart
编辑是为了确保问题不是来判断距离...我的gcdist()
例程会这样做并且例程有效(为简洁起见,它被遗漏了)......我需要做的更多是双 foreach
,以便测试每个 ll
与另一个 ll
对。有没有更好的方法来比较散列中的键:
我有一个包含以下内容的散列:
my %HASH
$HASH{"38.4486x122.7047"} = 1;
$HASH{"38.4487x122.7049"} = 10;
$HASH{"38.4489x122.7050"} = 14;
$HASH{"38.4491x122.7051"} = 20;
这个散列主要用于确保 -- 低至 4 个 dec 点,我没有重复项。我现在要做的是确保 HASH
中的所有这些点彼此之间的距离不在 30 英尺之内......(以上是测试数据,所以这些可能都不在 30 英尺之内......但是你明白我的意思)。
我有一个例程可以获取 lat/lon 点之间的距离。但这就是我(笨拙地)想出来的方式:
my %HASH_NEW;
foreach my $_ll_1 (sort {$a cmp $b} keys %HASH)
{
my ($_la1,$_lo1) = split ("x",$_ll_1);
my $keep_this_one = 1;
foreach my $_ll_2 (sort {$a cmp $b} keys %HASH)
{
# so we don't compare to the current one in the loop
next if $_ll_2 eq $_ll_1;
my ($_la2,$_lo2) = split ("x",$_ll_2);
if (gcdist([$_la1,$_lo1],[$_la1,$_lo1] < ~30ft)
{
$keep_this_one = 0;
last;
}
}
if ($keep_this_one)
{
$HASH_NEW{$_ll_1} = $HASH{$_ll_1};
}
}
sub gcdist
{
my $_ll1_arrayref = shift();
my $_ll2_arrayref = shift();
# get distance between $_ll1_arrayref and $_ll2_arrayref
# return it to caller
}
现在 %HASH_NEW 将包含 %HASH 的内容,30 英尺内没有 ll 对......或者我认为这是错误的?
TIA
迭代列表两次是置换,但这不是你想要的。你不关心顺序。 X 和 Y 之间的距离与 Y 和 X 之间的距离相同,没有理由计算两次。看看使用 Algorithm::Combinatorics 之类的东西来生成要测试的对。
在此之后,转储给定距离内的第一个坐标可能会产生糟糕的结果。假设有 4 个点,a b c d,距离为:
a <-> b = 40
a <-> c = 45
a <-> d = 25
b <-> c = 40
b <-> d = 20
c <-> d = 15
按顺序迭代这些对并在低于所需距离 30 时立即倾倒坐标将导致:
a thrown out; it's 25 from d
b thrown out; it's 20 from d
c thrown out, it's 15 from d
虽然您可能更愿意放弃 d,因为剩余的 3 分有效。
我会研究迭代组合对,计算并缓存所有组合的距离,然后开始一次丢弃具有最多接近点的数据点,直到 none 超过所需数量.
编辑是为了确保问题不是来判断距离...我的gcdist()
例程会这样做并且例程有效(为简洁起见,它被遗漏了)......我需要做的更多是双 foreach
,以便测试每个 ll
与另一个 ll
对。有没有更好的方法来比较散列中的键:
我有一个包含以下内容的散列:
my %HASH
$HASH{"38.4486x122.7047"} = 1;
$HASH{"38.4487x122.7049"} = 10;
$HASH{"38.4489x122.7050"} = 14;
$HASH{"38.4491x122.7051"} = 20;
这个散列主要用于确保 -- 低至 4 个 dec 点,我没有重复项。我现在要做的是确保 HASH
中的所有这些点彼此之间的距离不在 30 英尺之内......(以上是测试数据,所以这些可能都不在 30 英尺之内......但是你明白我的意思)。
我有一个例程可以获取 lat/lon 点之间的距离。但这就是我(笨拙地)想出来的方式:
my %HASH_NEW;
foreach my $_ll_1 (sort {$a cmp $b} keys %HASH)
{
my ($_la1,$_lo1) = split ("x",$_ll_1);
my $keep_this_one = 1;
foreach my $_ll_2 (sort {$a cmp $b} keys %HASH)
{
# so we don't compare to the current one in the loop
next if $_ll_2 eq $_ll_1;
my ($_la2,$_lo2) = split ("x",$_ll_2);
if (gcdist([$_la1,$_lo1],[$_la1,$_lo1] < ~30ft)
{
$keep_this_one = 0;
last;
}
}
if ($keep_this_one)
{
$HASH_NEW{$_ll_1} = $HASH{$_ll_1};
}
}
sub gcdist
{
my $_ll1_arrayref = shift();
my $_ll2_arrayref = shift();
# get distance between $_ll1_arrayref and $_ll2_arrayref
# return it to caller
}
现在 %HASH_NEW 将包含 %HASH 的内容,30 英尺内没有 ll 对......或者我认为这是错误的?
TIA
迭代列表两次是置换,但这不是你想要的。你不关心顺序。 X 和 Y 之间的距离与 Y 和 X 之间的距离相同,没有理由计算两次。看看使用 Algorithm::Combinatorics 之类的东西来生成要测试的对。
在此之后,转储给定距离内的第一个坐标可能会产生糟糕的结果。假设有 4 个点,a b c d,距离为:
a <-> b = 40
a <-> c = 45
a <-> d = 25
b <-> c = 40
b <-> d = 20
c <-> d = 15
按顺序迭代这些对并在低于所需距离 30 时立即倾倒坐标将导致:
a thrown out; it's 25 from d
b thrown out; it's 20 from d
c thrown out, it's 15 from d
虽然您可能更愿意放弃 d,因为剩余的 3 分有效。
我会研究迭代组合对,计算并缓存所有组合的距离,然后开始一次丢弃具有最多接近点的数据点,直到 none 超过所需数量.