【问题标题】:All possible replacements of two lists?两个列表的所有可能替换?
【发布时间】:2017-06-16 16:09:09
【问题描述】:

(我知道问题的标题可能具有误导性,但我找不到任何其他方式来表述它 - 请随时编辑它)

我有两个列表,长度相同:

a = [1,2,3]
b = [4,5,6]

我想用第二个列表获取第一个列表的所有可能替换。

output[0] = [1,2,3] # no replacements
output[1] = [4,2,3] # first item was replaced
output[2] = [1,5,3] # second item was replaced
output[3] = [1,2,6] # third item was replaced
output[4] = [4,5,3] # first and second items were replaced
output[5] = [4,2,6] # first and third items were replaced
output[6] = [1,5,6] # second and third items were replaced
output[7] = [4,5,6] # all items were replaced

请注意,以下问题无法回答此问题:

涉及先前链接的答案的可能解决方案是创建多个列表,然后对它们使用 itertools.product 方法。例如,我可以创建 3 个包含 2 个元素的列表,而不是 2 个包含 3 个元素的列表;但是,这会使代码过于复杂,如果可以的话,我宁愿避免这种情况。

有没有简单快捷的方法?

【问题讨论】:

    标签: python list python-3.x


    【解决方案1】:

    创建 3 个包含两个元素的列表根本不会使代码过于复杂。 zip can "flip the axes" of multiple lists琐碎(把Y元素的X序列变成X元素的Y序列),方便使用itertools.product

    import itertools
    
    a = [1,2,3]
    b = [4,5,6]
    
    # Unpacking result of zip(a, b) means you automatically pass
    # (1, 4), (2, 5), (3, 6)
    # as the arguments to itertools.product
    output = list(itertools.product(*zip(a, b)))
    
    print(*output, sep="\n")
    

    哪些输出:

    (1, 2, 3)
    (1, 2, 6)
    (1, 5, 3)
    (1, 5, 6)
    (4, 2, 3)
    (4, 2, 6)
    (4, 5, 3)
    (4, 5, 6)
    

    与您的示例输出的排序不同,但它是同一组可能的替换。

    【讨论】:

    • 注意:如果你真的想要lists,而不是tuples,output = list(map(list, itertools.product(*zip(a, b))))会将tuples转换回lists,但通常没有必要.
    【解决方案2】:

    每个项目都可以单独更换或单独放置。这可以通过位为 1 或 0 来建模。如果您将每个项目视为一个单独的位,那么迭代所有可能性可以映射到迭代所有 n 位的组合.

    换句话说,从 0 迭代到 2n-1 并查看位模式。

    n = len(a)
    for i in range(2**n):
        yield [a[j] if i & (1 << j) != 0 else b[j] for j in range(n)]
    

    打破这一点,i &amp; (1 &lt;&lt; j) != 0 检查是否设置了 i 的第 j 位。如果是,则使用a[j],否则使用b[j]

    结果:

    [1, 2, 3]
    [4, 2, 3]
    [1, 5, 3]
    [4, 5, 3]
    [1, 2, 6]
    [4, 2, 6]
    [1, 5, 6]
    [4, 5, 6]
    

    【讨论】:

      【解决方案3】:

      好的,这与其他答案相似,但从两者中吸取了一点。您可以将问题建模为查找给定长度序列的所有可能位,并仅在有 1 时替换,否则不替换。

      from itertools import product
      
      a = [1,2,3]
      b = [4,5,6]
      
      ## All binary combinations of length of a (or b)
      combinations = product([0,1], repeat=len(a))
      
      for combination in combinations:
          y = []
          for l, i in zip(zip(a,b),combination):
               y.append(l[i])
          print y
      

      所有位组合为:

      (0, 0, 0)
      (0, 0, 1)
      (0, 1, 0)
      (0, 1, 1)
      (1, 0, 0)
      (1, 0, 1)
      (1, 1, 0)
      (1, 1, 1)
      

      结果:

      [1, 2, 3]
      [1, 2, 6]
      [1, 5, 3]
      [1, 5, 6]
      [4, 2, 3]
      [4, 2, 6]
      [4, 5, 3]
      [4, 5, 6]
      

      【讨论】:

      • 虽然这可行,但我认为没有理由更喜欢它而不是直接获取元素的产品。计算索引然后索引就像做for i in range(len(someseq)): x = someseq[i](并且再也不会使用i),这是惯犯C程序员提交的Python中最直接的反模式之一,速度较慢,灵活性较差(不适用于迭代器),比 for usefulname in someseq: 更冗长,更少自我记录。
      • @ShadowRanger 我同意,我也会直接获得产品。不过我把它放进去,因为它很容易理解。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-01-12
      • 2017-04-04
      • 1970-01-01
      • 1970-01-01
      • 2021-02-10
      • 2021-09-28
      • 2012-06-14
      相关资源
      最近更新 更多