python - 将代码点的 numpy 数组与字符串相互转换

标签 python arrays string numpy

我有一个很长的 unicode 字符串:

alphabet = range(0x0FFF)
mystr = ''.join(chr(random.choice(alphabet)) for _ in range(100))
mystr = re.sub('\W', '', mystr)

我想将其视为一系列代码点,因此目前我正在执行以下操作:

arr = np.array(list(mystr), dtype='U1')

我希望能够将字符串作为数字进行操作,并最终得到一些不同的代码点。现在我想反转转换:

mystr = ''.join(arr.tolist())

这些转换速度相当快且可逆,但会占用 list 中介不必要的空间量。

有没有一种方法可以在不首先转换为列表的情况下将 numpy unicode 字符数组与 Python 字符串相互转换?

事后的想法

我可以让 arr 显示为带有类似内容的单个字符串

buf = arr.view(dtype='U' + str(arr.size))

这会产生一个包含整个原件的 1 元素数组。反过来也是可能的:

buf.view(dtype='U1')

唯一的问题是结果的类型是np.str_,而不是str

最佳答案

fromiter 有效,但速度非常慢,因为它通过迭代器协议(protocol)。将数据编码为 UTF-32(按系统字节顺序)并使用 numpy.frombuffer 要快得多:

In [56]: x = ''.join(chr(random.randrange(0x0fff)) for i in range(1000))

In [57]: codec = 'utf-32-le' if sys.byteorder == 'little' else 'utf-32-be'

In [58]: %timeit numpy.frombuffer(bytearray(x, codec), dtype='U1')
2.79 µs ± 47 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

In [59]: %timeit numpy.fromiter(x, dtype='U1', count=len(x))
122 µs ± 3.82 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

In [60]: numpy.array_equal(numpy.fromiter(x, dtype='U1', count=len(x)), numpy.fr
    ...: ombuffer(bytearray(x, codec), dtype='U1'))
Out[60]: True

我使用 sys.byteorder 来确定是使用 utf-32-le 还是 utf-32-be 进行编码。此外,使用 bytearray 而不是 encode 会得到一个可变字节数组而不是不可变字节对象,因此生成的数组是可写的。


至于反向转换,arr.view(dtype=f'U{arr.size}')[0] 有效,但使用 item()速度更快一些,并生成一个普通的字符串对象,避免了 numpy.str_ 的行为与 str 不同的可能的奇怪边缘情况:

In [72]: a = numpy.frombuffer(bytearray(x, codec), dtype='U1')

In [73]: type(a.view(dtype=f'U{a.size}')[0])
Out[73]: numpy.str_

In [74]: type(a.view(dtype=f'U{a.size}').item())
Out[74]: str

In [75]: %timeit a.view(dtype=f'U{a.size}')[0]
3.63 µs ± 34 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

In [76]: %timeit a.view(dtype=f'U{a.size}').item()
2.14 µs ± 23.4 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

最后,请注意 NumPy 不像普通的 Python 字符串对象那样处理空值。 NumPy 无法区分 'asdf\x00\x00\x00''asdf',因此如果您的数据可能包含 null,则使用 NumPy 数组进行字符串操作是不安全的代码点。

关于python - 将代码点的 numpy 数组与字符串相互转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54424433/

相关文章:

python - 将 2D 数组复制到 3D 数组 - Python/NumPy

python - SQLAlchemy 和 sqlite 的嵌套事务

python - 将静态文件按字面意思插入 Jinja 模板而不解析它们

php - 将数组插入关系数据库仅适用于数据库中已存在的数组中的数据

javascript - 使用Javascript转换罗马数字的算法

php - 需要在 include()ed css 文件之间添加换行符

python - Django/PostgreSQL 与 TextField object_id 字段的通用关系

python - 通过sqlalchemy在postgresql中有两个序列键

c - array[index] = 0; 的目的是什么?

ruby - 如何从文本中删除零宽度空格字符