Python中二维列表的迭代,计算两个位置之间的距离

0 投票
2 回答
651 浏览
提问于 2025-04-17 20:40

我有一个二维列表(就是一个列表里面又包含了多个列表),里面记录了美国的几个地点,以及它们对应的纬度和经度。下面是前几个城市的例子:

"Millersville","CA",35.303850,-118.457860    #(city 1)
"Millersville","IL",39.451150,-89.158140     #(city 2)
"Millersville","IN",39.853100,‐86.091650     #(city 3)
"Millersville","MD",39.059550,-76.648020     #(city 4)

我想设置一个循环,来计算城市1和城市2之间的距离,使用它们的纬度和经度,然后把这个距离保存到 loc1_loc2 里。接着再计算城市1和城市3之间的距离,保存到 loc1_loc3,依此类推。这个过程需要对所有可能的城市组合都进行计算,并保存每一个距离值。下面是我尝试过的代码,但我就是无法让它顺利进行循环:

for i in range(len(places)):
    dlat = math.radians(float(places[i][2])-float(places[0][2]))
    dlon = math.radians(float(places[i][3])-float(places[0][3]))
    a = math.sin(dlat/2) * math.sin(dlat/2) + math.cos(math.radians(float(places[0][2]))) \
        * math.cos(math.radians(float(places[i][2]))) * math.sin(dlon/2) * math.sin(dlon/2)
    c = 2 * math.atan2(math.sqrt(a), math.sqrt(1-a))
    d = radius * c
    loc0_loc0 = d * 0.621371

print loc0_loc0

我哪里做错了?我该如何设置这个循环,让它能遍历我所有的城市(数量不确定,取决于我用的是哪个列表),并计算每一个城市之间的所有可能距离呢?

谢谢大家的帮助!

2 个回答

2

你的代码看起来很难读,这让人不太明白你想做什么。对于四个地点来说,需要计算的距离有 (4 x (4-1)) / 2 = 6 个,但如果地点数量增加,这个数字会迅速增长。在这里,我选择计算一个完整的 4 x 4 距离矩阵——显然,我做了一些多余的工作,你可能可以避免这些。

你的下标使用方式让人很难理解发生了什么,所以我在 for 循环中使用了解包赋值的方法,这样可以避免复杂的下标,并把数据的每个元素绑定到一个名字上。

import math
places = [
    ["Millersville", "CA", 35.303850, -118.457860],    #(city 1)
    ["Millersville", "IL", 39.451150, -89.158140 ],    #(city 2)
    ["Millersville", "IN", 39.853100, -86.091650 ],     #(city 3)
    ["Millersville", "MD", 39.059550, -76.648020 ]      #(city 4)
]
# One of the minus signs was weird
radius = 6371 # Mean radius in Km
distances = []
for nameA, stateA, latA, longA in places:
    dists_row = []
    for nameB, stateB, latB, longB in places:
        dlat = math.radians(latA-latB)
        dlon = math.radians(longA-longB)
        a = math.sin(dlat/2) * math.sin(dlat/2) + math.cos(math.radians(latA)) \
            * math.cos(math.radians(latB)) * math.sin(dlon/2) * math.sin(dlon/2)
        c = 2 * math.atan2(math.sqrt(a), math.sqrt(1-a))
        d = radius * c
        distance = d * 0.621371
        dists_row.append(distance)
    distances.append(dists_row)

for row in distances:
    print(row)

这段代码的输出是

[0.0, 1626.6140655454842, 1789.8845362720158, 2295.8829666956335]
[1626.6140655454842, 0.0, 165.46706149552824, 669.3166714199295]
[1789.8845362720158, 165.46706149552824, 0.0, 506.5281329453448]
[2295.8829666956335, 669.3166714199295, 506.5281329453448, 0.0]

结果看起来很对称,并且对角线上的值都是零,这让我有点放心,说明我在重写你的公式时可能没有搞错。这里有一个版本,它直接打印结果,而不是把结果存储在矩阵里。在这个版本中,我只计算每个距离一次。

radius = 6371 # Mean radius in Km
for stnum, (nameA, stateA, latA, longA) in enumerate(places):
    for nameB, stateB, latB, longB in places[stnum+1:]:
        dlat = math.radians(latA-latB)
        dlon = math.radians(longA-longB)
        a = math.sin(dlat/2) * math.sin(dlat/2) + math.cos(math.radians(latA)) \
            * math.cos(math.radians(latB)) * math.sin(dlon/2) * math.sin(dlon/2)
        c = 2 * math.atan2(math.sqrt(a), math.sqrt(1-a))
        d = radius * c
        distance = d * 0.621371
        print(nameA, stateA, "to", nameB, stateB, "is", distance, "miles")

从中得到的输出是

Millersville CA to Millersville IL is 1626.6140655454842 miles
Millersville CA to Millersville IN is 1789.8845362720158 miles
Millersville CA to Millersville MD is 2295.8829666956335 miles
Millersville IL to Millersville IN is 165.46706149552824 miles
Millersville IL to Millersville MD is 669.3166714199295 miles
Millersville IN to Millersville MD is 506.5281329453448 miles
0

像这样可能会有效...

resultDict = {}
for startCity in places:
    for endCity in places:
        startLocation = startCity[0] + ' ' + startCity[1]
        endLocation = endCity[0] + ' ' + endCity[1]
        resultLocations = [startLocation, endLocation]
        resultId = ','.join(resultLocations.sort())

        if startLocation == endLocation or resultId in resultDict:
            continue

        dlat = math.radians(float(startCity[2])-float(endCity[2]))
        dlon = math.radians(float(startCity[3])-float(endCity[3]))
        a = math.sin(dlat/2) * math.sin(dlat/2) + math.cos(math.radians(float(endCity[2]))) \
            * math.cos(math.radians(float(startCity[2]))) * math.sin(dlon/2) * math.sin(dlon/2)
        c = 2 * math.atan2(math.sqrt(a), math.sqrt(1-a))
        d = radius * c
        resultDict[resultId] = d * 0.621371

print resultDict

撰写回答