【问题标题】:Two separate lists with corresponding numbers. How to detect them remove them from the list?两个带有相应编号的单独列表。如何检测它们将它们从列表中删除?
【发布时间】:2016-10-09 10:12:52
【问题描述】:

我正在寻找一个程序,在 8x8 网格上随机生成硬币。我已经创建了两个列表(一个用于 X 坐标的列表和一个用于 Y 坐标的列表)。在这些列表中,两个坐标不能相同。很难解释,所以这里是我的例子:

[1, 7, 4, **6**, 9, 2, 3, **6**, 8, 0] (list for the x co-ordinate)
[9, 3, 3, **1**, 2, 8, 0, **1**, 6, 1] (list for the y co-ordinate)

因此,创建了两个列表。但是(6,1) 出现了两次。我不想要这个。那么,我将如何在我的代码中允许这一点,以确保忽略这一点并将数字重新生成为不同的坐标?我的代码如下,我真的不知道如何实现这样的系统!

def treasurePro():
    global coinListX, coinListY
    coinListX = []
    coinListY = [] 
    for x in range(10): 
        num = randint(0,8) 
        coinListX.append(num) 
        print(coinListX)
    for x in range(10): 
        num = randint(0,8)
        if num == 0 and coinListX[x] == 0:
            treasurePro() #goes back to the beginning to restart.  
        else:
            coinListY.append(num) 
            print(coinListY)

【问题讨论】:

    标签: python arrays list python-3.x


    【解决方案1】:

    不要创建两个带有坐标的列表,至少一开始不要。这只会使检测重复变得更加困难。

    您可以创建带有坐标的元组,这样您就可以检测重复项,或者甚至可以生成一系列整数来表示您的坐标,然后从中采样。后者效率极高。

    要创建元组,基本上你想创建 8 个唯一的这样的元组:

    def treasurePro():
        coords = []
        while len(coords) < 8:
            coord = randint(0, 8), randint(0, 8)
            if coord not in coords:
                coords.append(coord)
        # now you have 8 unique pairs. split them out
        coinListX, coinListY = zip(*coords)
    

    这并不是那么有效,因为coord not in coords 测试必须扫描随着每个新坐标而增长的整个列表。对于要选择的大量坐标,这可能会显着减慢速度。您必须添加一个额外的 seen = set() 对象,您还必须添加坐标并在循环中再次测试以解决该问题。不过还有更好的办法。

    您的棋盘尺寸为 9x9,因此您有 81 个唯一坐标。如果您在 range() object(Python 2 中的 xrange())上使用 random.sample(),您可以轻松创建 8 个唯一值,然后从中“提取”行号和列号:

    def treasurePro():
        coords = random.sample(range(9 * 9), 8)  # use xrange in Python 2
        coinListX = [c // 9 for c in coords]
        coinListY = [c % 9 for c in coords]
    

    这里random.sample() 保证您获得 8 个唯一坐标。

    这也比预先生成所有可能的元组更有效;在 Python 3 中使用 range() 使上述使用 O(K) 内存,其中 K 是您需要生成的值的数量,而预先创建所有坐标将占用 O(N^2) 内存(其中 N 是大小板面)。

    您可能仍希望存储(x, y) 坐标列表,而不是使用两个单独的列表。使用coords = [(c // 9, c % 9) for c in coords] 创建一个。

    【讨论】:

      【解决方案2】:

      您的板子足够小,您可以简单地生成所有可能性,取样,然后转置为 X 和 Y 所需的单独列表。

      possibilities = [(a,b) for a in range(10) for b in range(10)]
      places = random.sample(possibilities, 10)
      x,y = zip(*places)
      

      【讨论】:

      • 这当然比需要的内存要多得多。使用range() 效率更高,尤其是在网格变得更大的情况下。
      • @MartijnPieters - 我想,但是,就像我说的,它目前足够小,生成的代码足够简洁、清晰和快速,所以我很满意。
      【解决方案3】:

      你想生成随机坐标,但你也想拒绝任何 已经出现在列表中的一对坐标。 (顺便, 而不是两个单独的整数列表,我建议使用一个 有序对的列表,即两个整数的元组。)

      拒绝重复的一种方法是在现有列表中搜索 新套装。这是 O(n) 并且比它需要的要慢,尽管它 在 n 不能超过 64 的用例中肯定会起作用。

      另一种方法是维护第二个数据结构,您可以 在 O(1) 时间内查找 64 个单元中的每一个,例如一个 8x8 数组 布尔值。实际上,您可以单独使用这一结构;得到一个 使用的坐标列表,遍历即可。

      【讨论】:

        【解决方案4】:
        cordX = [x for x in range(10)]
        cordY = cordX[:] 
        random.shuffle(cordX)
        random.shuffle(cordY)
        

        【讨论】:

          猜你喜欢
          • 2016-04-10
          • 1970-01-01
          • 1970-01-01
          • 2015-07-08
          • 1970-01-01
          • 2020-04-18
          • 2020-08-04
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多