str.join(iterable)方法是如何在Python/线性时间字符串连接中实现的

2024-09-30 10:33:11 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试用Python实现我自己的str.join方法,例如: ''.join(['aa','bbb','cccc'])返回'aabbbcccc'。我知道使用join方法进行字符串连接将导致线性(结果的字符数)复杂性,我想知道如何做到这一点,因为在for循环中使用'+'运算符将导致二次复杂性,例如:

res=''
for word in ['aa','bbb','cccc']:
  res = res +  word

由于字符串是不可变的,因此在每次迭代时复制一个新字符串,从而产生二次运行时间。然而,我想知道如何在线性时间内完成,或者找到''.join是如何精确工作的

我在任何地方都找不到线性时间算法,也找不到str.join(iterable)的实现。非常感谢您的帮助


Tags: 方法字符串for时间res线性字符word
1条回答
网友
1楼 · 发布于 2024-09-30 10:33:11

str作为实际的str连接是一种转移注意力的做法,而且not what Python itself does:Python操作可变的bytes,而不是str,这也消除了对know string internals的需要。具体来说,str.join将其参数转换为字节,然后pre-allocatesmutates its result

这直接对应于:

  1. str参数编码/解码到bytes或从bytes进行编码/解码的包装器
  2. 对元素和分隔符的len求和
  3. 分配可变的bytesarray来构造结果
  4. 将每个元素/分隔符直接复制到结果中
# helper to convert to/from joinable bytes
def str_join(sep: "str", elements: "list[str]") -> "str":
    joined_bytes = bytes_join(
        sep.encode(),
        [elem.encode() for elem in elements],
    )
    return joined_bytes.decode()

# actual joining at bytes level
def bytes_join(sep: "bytes", elements: "list[bytes]") -> "bytes":
    # create a mutable buffer that is long enough to hold the result
    total_length = sum(len(elem) for elem in elements)
    total_length += (len(elements) - 1) * len(sep)
    result = bytearray(total_length)
    # copy all characters from the inputs to the result
    insert_idx = 0
    for elem in elements:
        result[insert_idx:insert_idx+len(elem)] = elem
        insert_idx += len(elem)
        if insert_idx < total_length:
            result[insert_idx:insert_idx+len(sep)] = sep
            insert_idx += len(sep)
    return bytes(result)

print(str_join(" ", ["Hello", "World!"]))

值得注意的是,虽然元素迭代和元素复制基本上是两个嵌套循环,但它们在不同的对象上进行迭代。该算法仍然只接触每个字符/字节三次/一次

相关问题 更多 >

    热门问题