Python,在2个列表列表之间进行迭代,查看一个列表中的值是否与另一个列表中的值类似并提取它们

时间:2015-01-28 15:11:05

标签: python list iterator iteration nested-lists

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

    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范围。 (为了澄清,我正在搜索的坐标集必须在x范围内,并且在LBCoord和CoreCoord中的任何位置内彼此的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和斐济兼容的脚本来执行,因此一些导入的工具不起作用。

任何帮助将不胜感激!

非常感谢,

2 个答案:

答案 0 :(得分:0)

您可以使用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])]

答案 1 :(得分:0)

对两个列表中的笛卡尔积进行简单过滤会产生您想要的效果,但运行时间可能是不可接受的。让我们从那开始:

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

所以这个例子大大简化了,但希望它能为你展示一种改进的匹配方法。