在 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 超过所需数量.