【问题标题】:Swapping indices with values in a Python list?用 Python 列表中的值交换索引?
【发布时间】:2015-04-09 05:14:29
【问题描述】:

(不,这既不是家庭作业也不是竞赛,尽管它看起来很像。)

我在 Python 中有一个列表 A,其中包含数字 range(0, len(A))。数字不按顺序排列,但都在列表中。

我正在寻找一种简单的方法来构建一个列表B,其中索引和值已被交换,即一个列表,对于每个整数n,包含nA 中的位置.

例子:

A = [0, 4, 1, 3, 2]
B = [0, 2, 4, 3, 1]

我可以将生成B 的代码单独或放在生成A 的代码中。特别是,这是我生成 A 的方式:

A = [value(i) for i in range(length)]

最好的方法是什么?

【问题讨论】:

    标签: python list python-3.x swap indices


    【解决方案1】:

    如何分配给预先分配的B:

    >>> A = [0, 4, 1, 3, 2]
    >>> B = [0] * len(A)
    >>> for k, v in enumerate(A): B[v] = k
    >>> B
    [0, 2, 4, 3, 1]
    

    那将是 O(n)。

    【讨论】:

      【解决方案2】:

      使用enumerate() function 用它们的索引装饰每个值,用sorted() 对值进行排序,然后再次取消装饰以按值顺序提取索引:

      [i for i, v in sorted(enumerate(A), key=lambda iv: iv[1])]
      

      这具有 O(NlogN) 时间复杂度,因为我们使用了排序。

      演示:

      >>> A = [0, 4, 1, 3, 2]
      >>> [i for i, v in sorted(enumerate(A), key=lambda iv: iv[1])]
      [0, 2, 4, 3, 1]
      

      我们还可以使用预先构建的列表来为 O(N) 解决方案分配索引:

      B = [0] * len(A)
      for i, v in enumerate(A):
          B[v] = i
      

      演示:

      >>> B = [0] * len(A)
      >>> for i, v in enumerate(A):
      ...     B[v] = i
      ... 
      >>> B
      [0, 2, 4, 3, 1]
      

      如果时间复杂度是个大问题,这可能是更好的选择;对于 N = 100,排序方法大约需要 461 步,而预建列表方法需要 100 步。

      【讨论】:

      • 我看不出有任何理由使用sorted 解决方案
      【解决方案3】:
      A = [0, 4, 1, 3, 2]
      
      B = [None]*len(A)
      
      for i, x in enumerate(A):
          B[x] = i
      
      print B
      

      回复:[0, 2, 4, 3, 1]

      【讨论】:

      • [None]*len(A) 包裹在list(...) 中没有任何效果
      【解决方案4】:

      这很幼稚;

      [ [ x[0] for x in enumerate(A) if x[1] == i][0] for i in range(len(A)) ]

      这很完美,

      [A.index(A.index(i)) for i in A]  
      

      更好

      [A.index(i[0]) for i in enumerate(A)]
      

      这个击败另一个;

      [A.index(i) for i in range(len(A))]
      

      证明;

      import random as r
      for l in [ r.sample(range(5),5) for n in range(5) ]:
          A = l
          B = [A.index(A.index(i)) for i in A]
          print "A is : ", A
          print "B is : ", B
          print "Are B's elements indices of A? : ", A == [B.index(B.index(i)) for i in B]
          print
      

      【讨论】:

      • 非常效率低下。这是一个 O(N^2) 二次方法;如果您对包含 100 个元素的列表执行此操作,您将进行 100.000 次比较。对于具有 1.000.000 个元素的列表,这将是 1.000.000.000.000 次比较。
      • @martijn-pieters 感谢 cmets。我已经更新了我的帖子,还有更多的 cmets 吗?
      • list.index() 仍然是一个 O(N) 步骤。它看起来只是一个命令,但 Python 仍然需要扫描列表以找到第一个匹配项并返回索引。
      猜你喜欢
      • 1970-01-01
      • 2021-12-17
      • 2016-04-03
      • 1970-01-01
      • 1970-01-01
      • 2023-01-30
      • 1970-01-01
      • 2018-12-10
      • 1970-01-01
      相关资源
      最近更新 更多