【问题标题】:Is there an efficient way to change all the elements in a list such that the lowest number becomes a zero, and each number after has integer spacing?有没有一种有效的方法来更改列表中的所有元素,使最小的数字变为零,并且之后的每个数字都有整数间距?
【发布时间】:2022-01-31 18:54:08
【问题描述】:

我想总体上实现以下目标,理想情况下不使用 for 循环来单步执行每个元素,因为这似乎效率低下。列表的每个元素都将是 int 类型。

3 个例子:

In  [1]: L1 = [3,6,19,6,3,3,19]
In  [2]: f(L1)
Out [2]: [0,1,2,1,0,0,2]

In  [3]: L2 = [0,1,2,4,1,4,1,0]
In  [4]: f(L2)
Out [4]: [0,1,2,3,1,3,1,0]

In  [5]: L3 = [2,3,3,4,2,2,3,4]
In  [6]: f(L3)
Out [6]: [0,1,1,2,0,0,1,2]

数字的顺序无关紧要,但相对频率很重要。

如果数字之间没有空格,我当前的尝试就可以工作 - 就像在 L3 中一样。

我的尝试:

def f(L):
    L = np.array(L) - min(L)
    return list(L)

但这显然不能按照我想要的方式处理差异。如果我可以避免 L 的每个元素的 for 循环,并且还避免进行元素比较(例如检查 L1 中 19 之后的下一个最小数字是否为 6),那将是理想的,但对我来说并不明显有一种方法可以避免这种情况。

【问题讨论】:

  • 您的输出似乎将每个数字替换为第一次出现的数字的索引?
  • 我认为意图是根据其在原始数据中的排名来替换数字。每次出现时,最小值变为 0,下一个最小值变为 1,依此类推。
  • @KarlKnechtel 完全正确。这就是我想要做的。我现在正在实施第一个建议,如果它符合我的要求,我会将其标记为已接受的答案。否则,我将编辑我的问题以提供更多/更好的上下文。

标签: python list integer


【解决方案1】:

我认为您不可能在 O(n) 时间内完成此操作,因此尝试避免列表上的 for 循环是没有用的。这是我要采取的方法:

>>> def f(nums):
...     m = {num: i for i, num in enumerate(sorted(set(nums)))}
...     return [m[num] for num in nums]
...
>>> f([3,6,19,6,3,3,19])
[0, 1, 2, 1, 0, 0, 2]
>>> f([0,1,2,4,1,4,1,0])
[0, 1, 2, 3, 1, 3, 1, 0]
>>> f([2,3,4,4,2,2,3,4])
[0, 1, 2, 2, 0, 0, 1, 2]

注意排序是O(m log m),其中m是唯一数的个数,所以最坏的情况是O(n log n)。

【讨论】:

    【解决方案2】:

    注意,如果您实际上是使用 numpy 开始的,则可以将 numpy.unique 与 return_inverse=True 参数一起用于此特定分解:

    >>> np.unique(L1, return_inverse=True)
    (array([ 3,  6, 19]), array([0, 1, 2, 1, 0, 0, 2]))
    

    这应该是非常高效的,但您应该针对您的特定用例进行配置。请注意,这具有您想要的行为,因为 np.unique 将返回数组的 排序 唯一元素。

    【讨论】:

    • 第一种方法通常看起来是不正确的,隐含地假设第一次看到一个 int i,在它之前没有看到比 i 更大的东西。例如,将其应用于[3, 2, 1, 0],结果为[0, 1, 2, 3],这与“最小数字变为零”的要求相矛盾。我假设第二种方法也是如此,但没有检查它。
    • @TimPeters "最小的数字变成零" 啊,没注意到这个要求。好的,删除了第一种方法。第二个实际上不是这样工作的。我没有仔细阅读,被“顺序无关紧要”弄糊涂了
    • 您的解决方案是我要使用的解决方案,因为我使用的是 numpy,但我将把另一个问题标记为正确,因为我没有明确说我使用的是 numpy,所以我认为它更好地回答了我提出的问题。但如果有人让我知道这是否是堆栈溢出的错误礼仪,我将不胜感激。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-08-23
    • 2019-09-13
    • 1970-01-01
    • 1970-01-01
    • 2015-08-04
    • 1970-01-01
    • 2020-11-20
    相关资源
    最近更新 更多