【问题标题】:how to find an element in a nested structure and return index如何在嵌套结构中查找元素并返回索引
【发布时间】:2020-01-11 17:05:03
【问题描述】:

我有一个由列表列表表示的方形网格 - 例如:

grid = [[[9,3], [], [4]], 
        [[10, 1, 2], [], [11,5]],
        [[8], [7, 6], []]]

最里面的列表(单元格)的长度没有限制。网格必须包含从 1 到 n 的所有整数,其中 n 是给定的数字(在本例中为 11),每个数字只能出现一次。

我需要以均匀的概率选择一个介于 1 和 n 之间的随机数并返回该数字的位置(即对于“3”,我需要 grid[0][0][1])。因为概率需要统一,所以我不能只选择一个随机单元格,然后在单元格中选择一个随机数,因为这会使选择偏向单元格中数字较少的单元格中的数字。

我最初的方法是生成一个介于 1 和 n 之间的随机数,然后在整个网格中查找该数字。但是,网格可以变得非常大。解决这个问题的最佳方法是什么?

【问题讨论】:

  • 为什么random.randint 不够统一? “网格”如何影响选择的均匀性?
  • 这个“网格”是如何填充的,它代表什么?如果性能成为问题,最好使用不同的数据结构
  • @DeepSpace 我们还需要获取随机生成数字的位置
  • 所以你的问题真的是“如何在嵌套结构中找到一个元素”,而不是“如何随机选择一个数字”,对吗?如果是,请编辑问题
  • because that would bias the selection towards numbers in cells with fewer numbers in them.,怎么样?只需为两个索引选择 2 个随机数(统一)。使用grid[index1][index2] 转到索引,你会得到一个列表。现在,如果获得的列表不为空,则从列表中随机选择一个数字。整个过程需要恒定的时间(O(1))。

标签: python list random


【解决方案1】:

如果您必须在网格中查找多个项目,您可以创建数组的映射,然后在位置字典中查找随机数。但是,如果您只需要在网格中找到一个数字,那么您可以直接通过它直到找到它。

grid = [[[9,3], [], [4]], 
        [[10, 1, 2], [], [11,5]],
        [[8], [7, 6], []]]

locations = {n: (i, j, k)
    for i in range(len(grid))
    for j in range(len(grid[0]))
    for k, n in enumerate(grid[i][j])
}

print(locations)
# {
#   1: (1, 0, 1), 
#   2: (1, 0, 2), 
#   3: (0, 0, 1), 
#   4: (0, 2, 0), 
#   5: (1, 2, 1), 
#   6: (2, 1, 1), 
#   7: (2, 1, 0), 
#   8: (2, 0, 0), 
#   9: (0, 0, 0), 
#   10: (1, 0, 0), 
#   11: (1, 2, 0)
# }

rand_int = random.choice(locations.keys())
print(rand_int, locations[rand_int])
# (10, (1, 0, 0))

【讨论】:

    【解决方案2】:

    您可以创建 dict 来像这样映射您的数组数组

    arrays_map = {9:'1,1,1', 3: '1,1,2'...}
    n = len(arrays_map.values())
    random_number = arrays_map[radom.randint(0, n)]
    

    【讨论】:

    • 我不确定这比遍历整个网格并找到匹配项更快。如何快速创建arrays_map?
    • arrays_map 是你只做一次的计算,它还允许你轻松地随机而不带偏见
    【解决方案3】:

    如果你有可变深度的嵌套数字列表,你可以这样做,代码并不完美,只是为了演示这个想法

    import random
    
    grid = [[[9,3], [], [4]], 
            [[10, 1, 2], [], [11,5]],
            [[8], [7, 6], []]]
    
    
    number_index_map = dict()
    def create_map(grid, index_string): # you could other useful datastructure like list or tuple for storing the index_string
        for i, val in enumerate(grid):
            if isinstance(grid[i], list):
                next_index_string = "%s,%d"%(index_string, i) if len(index_string) else "%d"%(i)
                create_map(grid[i], next_index_string)
            else:
                key = "%s,%d"%(index_string, i) if len(index_string) else "%d"%(i)
                number_index_map[val] = key
    
    create_map(grid, "")
    print(number_index_map)
    
    
    #test
    n = 11
    random_number = random.randint(1, n)
    print("random number %d " % random_number)
    random_number_index = number_index_map[random_number]
    print("random number index %s"%random_number_index)
    
    # to get back the number from the index string
    temp = grid
    list_index = random_number_index.split(",")
    print("list index ", list_index)
    for i in list_index:
        temp=temp[int(i)]
    print(temp)
    

    【讨论】:

      【解决方案4】:

      如果我很好理解这个问题,我建议我们可以使用递归来搜索列表中的各种维度和长度并找到一个数字及其位置:

      import random
      
      grid = [[[9,3], [], [4]], 
              [[10, 1, 2], [], [11,5]],
              [[8], [7, 6], []]]
      
      def lookfor(num, grid, pos=[]):
      
          for i in range(len(grid)):
      
              if isinstance(grid[i], list):
                  pos.append(i)
                  pos2 = lookfor(num, grid[i], pos[:])
                  if pos2 != pos:
                      return pos2
                  else:
                      pos.pop()
      
              elif grid[i] == num:
                  pos.append(i)
                  return pos
      
          return pos
      
      num = random.randint(1, 11)
      
      print(num, '>', lookfor(num, grid))
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-01-17
        • 1970-01-01
        • 2020-11-09
        • 1970-01-01
        • 2014-11-10
        • 2017-03-03
        • 2019-07-31
        • 2016-02-29
        相关资源
        最近更新 更多