【问题标题】:Map string to integers with position in ASCII table将字符串映射到 ASCII 表中具有位置的整数
【发布时间】:2021-02-10 17:14:53
【问题描述】:

我有一个这样的字符串:

word = 'python'

基于string.ascii_lowercase,我想创建一个如下所示的新数组:

[15, 24, 19, 7, 14, 13]

我对这个问题的解决方案是:

alphabet = {char: i for i, char in enumerate(string.ascii_lowercase)}
indices = [alphabet[char] for char in word]
print(indices)

输出:[15, 24, 19, 7, 14, 13]

但我正在寻找一种更有效的方法,而不使用循环。我怎样才能以矢量化的方式做到这一点?

【问题讨论】:

  • [ord(c) - 0x61 for c in word]
  • @OlvinR​​oght 这不是矢量化的方式。它使用列表理解。
  • 我知道,但这是使用 python 最快的方法。
  • 这是典型的大小字符串吗?或者您正在使用更长的字符串?

标签: python string numpy unicode vectorization


【解决方案1】:

一种方法是使用 np.fromiter 从字符串构建一个数组,并指定一个 'U1' dtype,转换为整数,然后减去 unicode 表中字母表的起始位置,97 或者我们可以只使用ord('a'): 由 Antoine Dubuis 建议:

import numpy as np
word = 'python'
np.fromiter(word, dtype='U1').view(np.uint32) - ord('a')
array([15, 24, 19,  7, 14, 13])

【讨论】:

  • 您确定np.fromiter 在这里进行矢量化操作吗?通过文档,似乎是一个通用实用程序,可能类似于 np.vectorize?然后通过运行时数字,似乎是线性缩放 w.r.t。输入的大小,建议在 Python 级别进行迭代。
  • 是的,从运行时数字来看确实如此,差异很大。我会认为创建数组,当然在这两种情况下都应该是O(n),无论如何都是必要的步骤,并且下降到C。可能是强制dtype到U1然后铸造速度要慢得多。或者可能更像你所说的那样,它主要是一个便利功能。不确定@divakar
【解决方案2】:

我们可以使用np.frombuffer 来获得相当高效的 -

import numpy as np

np.frombuffer(word.encode(), dtype=np.uint8)-97

1M 长字符串的计时:

In [23]: import string

In [24]: p = string.ascii_lowercase

In [25]: word = ''.join([p[i] for i in np.random.randint(0,len(p), 1000000)])

In [26]: %timeit np.frombuffer(word.encode(), dtype=np.uint8)-97
136 µs ± 1.01 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

# @yatu's soln with np.fromiter
In [27]: %timeit np.fromiter(word, dtype='U1').view(np.uint32) - ord('a')
24.8 ms ± 423 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

【讨论】:

    猜你喜欢
    • 2018-10-18
    • 2017-06-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-14
    • 2016-08-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多