【问题标题】:How to go through a double for loop randomly in python如何在python中随机通过双循环
【发布时间】:2017-09-21 02:42:11
【问题描述】:

考虑以下代码:

for i in range(size-1):
    for j in range(i+1,size):
        print((i,j))

我需要以随机方式执行这个 for 循环。我试图写一个生成器来做这样的事情

def Neighborhood(size):
    for i in shuffle(range(size-1)):
        for j in shuffle(range(i+1), size):
            yield i, j
for i,j in Neighborhood(size):
    print((i,j))

但是,随机播放不能应用于任何对象范围。我不知道如何补救这种情况,非常感谢任何帮助。我希望有一个解决方案避免将范围转换为列表,因为我需要速度。例如,大小可能约为 30,000,我将执行此 for 循环大约 30,000 次。

我还计划尽早退出 for 循环,因此我想避免包含 shuffle(list(range(size))) 的解决方案

【问题讨论】:

  • 如果你真的需要洗牌,你可以使用list(range())
  • 我认为你所要求的是不可能的。您想以随机顺序遍历 (i, j) 的所有可能组合,但如果您不想重复,则有必要记住您已经使用过哪些组合。这需要 O(size^2) 空间。但我认为你可以比 shuffle(range) 做得稍微好一点。
  • 为什么不直接产生随机数?
  • 这暗示着“我需要以随机方式通过这个 for 循环”。但也许乔纳森会澄清。
  • 这样可以吗,即使是洗牌,你也可以一次遍历你的三角形吗?

标签: python for-loop generator


【解决方案1】:

您可以使用random.sample

使用random.sample 优于random.shuffle 的优点是,它可以在迭代器上工作,所以在:

  • Python 3.X 不需要将 range() 转换为列表
  • 在 Python 2,X 中,您可以使用 xrange
  • 相同的代码可以在 Python 2.X 和 3.X 中运行

示例代码:

n=10
l1=range(n)
for i in sample(l1,len(l1)):
    l2=range(i,n)
    for j in sample(l2,len(l2)):
        print(i,j)

编辑:

至于我为什么要进行此编辑,请查看 cmets。

def Neighborhood(size):
    range1 = range(size-1)
    for i in sample(range1, len(range1)):
        range2 = range(i+1)
        for j in sample(range2, len(range2)):
            yield i, j

【讨论】:

  • 我已经提供了 OP 所需的一切。用勺子喂别人不是我们的工作。正如他们所说,与其把鱼交给别人,不如教别人钓鱼。
  • 感谢您的意见@KaushikNP
  • 当然。很高兴帮助@JonathanDavidson。不要以为我不知道谁对我的回答投了反对票 Stefan Pochmann
  • @JonathanDavidson 如果您在实施方面需要任何帮助,请告诉我:)
  • 响应的实现应该很简单,但感谢您的提议。
【解决方案2】:

一种真正随机的简单方法,而不是逐行:

def Neighborhood(size):
    yielded = set()
    while True:
        i = random.randrange(size)
        j = random.randrange(size)
        if i < j and (i, j) not in yielded:
            yield i, j
            yielded.add((i, j))

演示:

for i, j in Neighborhood(30000):
    print(i, j)

打印类似:

2045 5990
224 5588
1577 16076
11498 15640
15219 28006
8066 10142
7856 8248
17830 26616
...

注意:我假设您确实会“提前退出 for 循环”。这样就不会出现由于重复生成对而导致减速的问题。

【讨论】:

  • 这绝对是我将尝试与线程中的其他建议一起实施的一种方法,尤其是与模拟退火相结合。我是否可以修改代码以使其作为生成器运行,这样我就不会提前创建整个集合,或者此代码是否已经到期。抱歉,我是生成器和 yield 命令的新手。
  • @JonathanDavidson 它已经是一个生成器了。顺便说一句,你说你“想避免包含 shuffle(list(range(size))) 的解决方案”,但后来你接受了一个实际上完全做到这一点的解决方案......
  • 我认为对迭代器进行采样不会那样做。我的错。我已经在我的算法的不同版本中尝试了你的解决方案和其他解决方案,我正在测试哪种方法效果更好。感谢您的贡献。
【解决方案3】:

我不认为你可以随机遍历一个迭代器。不过,您可以预定义洗牌列表

random iteration in Python

L1 = list(range(size-1))
random.shuffle(L1) 
for i in L1:
    L2 = list(range(i+1, size))
    random.shuffle(L2) 
    for j in L2:
        print((i,j))

当然,对于大型列表来说不是最优的

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-11
    • 1970-01-01
    • 2016-12-29
    • 1970-01-01
    • 2019-02-22
    • 1970-01-01
    • 2012-01-08
    • 2022-01-17
    相关资源
    最近更新 更多