【问题标题】:Python, iterating between 2 lists of lists, seeing if values in one list are similar to values in the other and extracting themPython,在 2 个列表列表之间迭代,查看一个列表中的值是否与另一个列表中的值相似并提取它们
【发布时间】:2015-03-27 13:17:33
【问题描述】:

我有两个包含笛卡尔坐标的列表:

    LBCoord = [[1195,456],[1324,674],[5644,687],[4679,654]] #very long list
    CoreCoord = [[1145,466],[1524,644],[5664,657],[4479,654]] #very long list

我想遍历这两个列表,查看 x (LBCoord[n][0]) 和 y (LBCoord[n][1]) 中的两组坐标中的任何一组是否在用户确定的范围内x 和 y 范围。 (为了澄清,我正在搜索的坐标集需要在 LBCoord 和 CoreCoord 中的任何位置内的 x 范围内和 y 范围内)

    #user determined x and y ranges
    xRange = 3
    yRange = 5
    LBCoord = [[1000,400],[1324,674],[5644,687],[4679,654]] #very long list
    CoreCoord = [[1145,466],[1524,644],[5664,657],[997,395]] #very long 

如果 LBCoord 包含坐标 [1000,400] 而 CoreCoord 包含 [997,395],我希望程序打印出这些坐标集(因为它们在 xRange 和 yRange 内)并继续运行。

我尝试过使用嵌套的 for 循环,但这些循环最终会拉出坐标的重复/排列,这是一个问题,因为在 jython 脚本中实现时它们很难处理。

另一个需要解决的问题是,这需要使用与 Python 2.5 和斐济兼容的脚本执行,因此某些导入的工具不起作用。

任何帮助将不胜感激!

非常感谢,

【问题讨论】:

  • 你所谓的xRangeyRange其实是对应的LBCoord/CoreCoord之间可以接受的距离
  • 那么,您的 xRange 和 yRange 将是数千而不是数字,对吧?您想从列表中获取位于 x 和 y 范围内的所有坐标的列表吗?

标签: python list iterator iteration nested-lists


【解决方案1】:

对两个列表的笛卡尔积进行简单过滤会产生您想要的结果,但运行时间可能无法接受。让我们开始吧:

match_pairs = []
for current_lb_coord in LBCoord:
    for current_core_coord in CoreCoord:
        if abs(current_lb_coord[0] - current_core_coord[0]) <= xRange
            and abs(current_lb_coord[1] - current_core_coord[1]) <= yRange:
            match_pairs.append((current_lb_coord, current_core_coord))

这将创建一个元组列表,其中首先是 LBCoord,其次是 CoreCoord。但是,它可能需要很长时间才能运行,因为您需要对两个列表中的每一对进行比较 - 所以它具有 O(m * n) 复杂性。

接下来就是尝试优化它。由于您确实有两个过滤器,因此您知道如果其中一个的变化太大,那么另一个是否很好匹配并不重要。鉴于此,您可以按 x 坐标对两个列表进行排序。然后,您可以对两个列表进行操作,寻找重叠良好的点。

对列表进行排序需要O(n log n) 时间。完成后,您应该能够并行运行两个列表一次(实际上它比这更复杂),因此这应该会减少一些时间。复杂性在于您可以为给定条目匹配多个匹配项。

在下面的代码中,我将假设只有 x 坐标很重要。您应该使用此代码并对其进行增强以包含 y 坐标。对列表进行排序然后对两者进行操作的基本过程应该可以让您获得很好的加速:

sorted_lb_coords = sorted(LBCoord)
sorted_core_coords = sorted(CoreCoord)
lb_index = core_index = 0
match_pairs = []

while lb_index < len(sorted_lb_coords) and core_index < len(sorted_core_coords):
    current_lb = sorted_lb_coords[lb_index]
    current_core = sorted_core_coords[core_index]

    # Remember I am only considering x
    if abs(current_lb - current_core) < limit:
        match_pairs.append((current_lb, current_core))

    # This part may also be more complex if you want all available matches.
    # You could run through all the current_core entries till one was out
    # of range and then reset the current_core index and increment the
    # current_lb index.
    if current_lb < current_core:
        current_lb = current_lb + 1
    else:
        current_core = current_core + 1

因此,此示例已大大简化,但希望它可以向您展示这种匹配的改进方法。

【讨论】:

  • 速度可以接受,非常感谢您的帮助!
【解决方案2】:

您可以使用filterzip

>>> filter(lambda x : abs(x[0][0]-x[1][0])==145 and abs(x[0][3]-x[1][4])==66 , zip(LBCoord,CoreCoord))
[([1000, 400], [1145, 466])]

【讨论】:

  • 感谢您的帮助!
  • @BenMargetts 欢迎您,如果您觉得这个答案有帮助,您可以通过投票告诉社区或接受它
  • zip 不会将一个列表中的每个条目与另一个列表配对,它只会将相同索引的条目配对。这意味着您不会找到所有匹配项。
猜你喜欢
  • 2021-02-23
  • 2021-10-06
  • 2020-05-11
  • 1970-01-01
  • 2022-10-04
  • 1970-01-01
  • 2023-02-22
  • 1970-01-01
  • 2021-08-09
相关资源
最近更新 更多