压缩列表会在某些输入下创建重复项

问题描述 投票:0回答:1

我有一个函数可以根据给定的边界框创建网格。我最近遇到一种情况,在某些条件下,

zip
调用最终返回的数字远低于输入的预期排列。

考虑以下 MWE:

import numpy as np

def makegrid(xmin, ymin, xmax, ymax):
  
  xmin = int(np.floor(xmin / 1000) * 1000)
  ymin = int(np.floor(ymin / 1000) * 1000)
  xmax = int(np.ceil(xmax / 1000) * 1000)
  ymax = int(np.ceil(ymax / 1000) * 1000)
  
  left_list = [ left for bottom in range(ymin, ymax, 1000) for left in range(xmin, xmax, 1000) ]
  bottom_list = [ bottom for left in range(xmin, xmax, 1000) for bottom in range(ymin, ymax, 1000) ]
  
  right_list = [left + 1000 for left in left_list]
  top_list = [bottom + 1000 for bottom in bottom_list]
  
  #edit - add print statement showing input dims
  print(f"dims: {len(left_list)}, {len(bottom_list)}, {len(right_list)}, {len(top_list)}")

  zip_coords = zip(left_list,bottom_list,right_list,top_list)
  zcoords = list(zip_coords)
  
  print(f"expecting: {len(set(left_list)) * len(set(bottom_list))} tiles")
  print(f"produced: {len(set(zcoords))} tiles")


#example one - works correctly
makegrid(452958.56 , 3684771.695,  551076.93 , 3846044.225)

#expecting: 16300
#produced: 16300

#example two - does not work and produces a fraction of expected
makegrid(518249.995, 3630269.23 ,  638616.78 , 3816623.475)

#expecting: 22627
#produced: 2057


#example three - add some jitter to example two, back to working correctly
makegrid(518249.995, 3640269.23 ,  640616.78 , 3856623.475)

#expecting: 26691
#produced: 26691

#example four - a different jitter, does not match
makegrid(519249.995, 3630169.23 ,  638516.78 , 3812623.475)

#expecting: 21960 
#produced: 7320

我已经验证每个输入列表的大小相同。我还尝试在 zip 调用中添加

strict=True
参数,但我无法弄清楚为什么 zip 函数会将条目向下折叠。

python raster
1个回答
0
投票

你的函数太复杂了。您想要的只是两个范围的笛卡尔积;为此,请使用

itertools.product
,而不是将两个多重集压缩在一起。

def makegrid(xmin, ymin, xmax, ymax):

  xmin = int(np.floor(xmin / 1000) * 1000)
  ymin = int(np.floor(ymin / 1000) * 1000)
  xmax = int(np.ceil(xmax / 1000) * 1000)
  ymax = int(np.ceil(ymax / 1000) * 1000)

  x_coords = range(xmin, xmax, 1000)
  y_coords = range(ymin, ymax, 1000)

  return list(product(x_coords, y_coords)) 

您还可以直接使用列表理解:

return [(x, y) for x in x_coords for y in y_coords]
© www.soinside.com 2019 - 2024. All rights reserved.