【问题标题】:Python |S1 vector to stringPython |S1 向量到字符串
【发布时间】:2020-10-13 18:30:30
【问题描述】:

我有一个 |S1 类型的向量“char”,如下例所示:

masked_array(data=[b'E', b'U', b'3', b'7', b'6', b'8', b' ', b' ', b' ', b' '],
             mask=False,
       fill_value=b'N/A',
            dtype='|S1')

我想获取其中的字符串,在本例中为“EU3768”

此示例取自 netcdf 文件。使用的库是 netCDF4。

再问:为什么所有单个字母前面都有一个b?

感谢您的帮助:)

【问题讨论】:

    标签: python-3.x string dtype


    【解决方案1】:

    首先让我们回答最基本的问题:每个字母前面的b是什么意思。 b 仅表示字符串以字节为单位。数据的内部格式以 utf-8 编码存储。因此,要将其转换回字符串,必须对其进行解码。因此,以此为序言,下面的代码就可以解决问题。

    我假设您可以从 masked_array 中提取数据。然后执行以下操作:

    #  Convert the list of bytes to a list of strings
    ds = list(map(lambda x: x.decode('utf-8'), data))
    
    #  Covert List of strings to a String and strip any trailing spaces
    sd = ''.join(ds).strip()
    

    这当然可以在一行代码中执行,如下所示:

    sd = ''.join(list(map(lambda x: x.decode('utf-8'), data))).strip()
    

    【讨论】:

    • 您无需将map(...) 转换为listmap(...) 创建一个generator expression 可以被join() 使用
    • 或者如果你和我一样觉得生成器表达式比 lambda 更直观,sd = ''.join(x.decode('utf-8') for x in data).strip()
    • 好点stackoverflow.com/users/843953/pranav-hosangadi,我只是想按步骤布局解决方案,并没有完全考虑。
    • 谢谢,这有点帮助,现在我明白这个“b”是什么意思了。我现在也可以从单个向量“char”中创建一个字符串。但是现在我遇到了另一个问题:在我的文件中大约有 100.000 个这些向量,每个向量都有 10 个条目,每个条目构建一个字符串。数据的形状是 (100.000,10)。所以最后应该有 100.000 个字符串。这种方法有效,但速度慢得令人难以置信,它并不是一个真正的选择。有没有办法在很短的时间内为所有 100.000 个向量执行此操作,因此不使用任何循环?
    • 我不知道你说的很长一段时间是什么意思,因为将列表转换为字符串需要 O(n) 时间,其中 n = 列表长度,我无法想象会有更快的方式来执行操作。我没有尝试为操作计时,但如果每次翻译大约需要 100 微秒,那么您仍然需要在大约 10 秒内翻译全部 100,000 次。
    【解决方案2】:

    作为对后续问题的回答,您可以让 Numpy 仅通过处理底层字节来完成一些工作。例如,我可以通过以下方式创建大量形状相似的对象:

    import numpy as np
    from string import ascii_letters, digits
    
    letters = np.array(list(ascii_letters + digits), dtype='S1')
    
    v = np.random.choice(letters, (100_000, 10))
    

    前三个元素如下所示:

    [[b'W' b'B' b'W' b'4' b'O' b'B' b'A' b'4' b'Q' b'n']
     [b'I' b'I' b'T' b'u' b'K' b'K' b'U' b'a' b'r' b'r']
     [b'V' b'f' b'n' b'U' b'G' b'0' b'j' b'R' b'm' b'C']]
    

    然后我可以通过一些字节级别的 shanigans 将这些转换回字符串:

    [bytes.decode(s) for s in np.frombuffer(v, dtype='S10')]
    

    前三个看起来像:

    ['WBW4OBA4Qn', 'IITuKKUarr', 'VfnUG0jRmC']
    

    希望这是有道理的。这需要大约 20 毫秒,这比通过 Python 的版本要快:

    [b''.join(r).decode() for r in v]
    

    大约需要 200 毫秒。这仍然比您发布的代码版本快得多,所以也许您可以更有效地访问 netcdf。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-02
      • 1970-01-01
      • 1970-01-01
      • 2020-07-01
      • 1970-01-01
      相关资源
      最近更新 更多