python - 字符串的快速串联

标签 python string numpy cython

我有一个二维 0/1 数组,X。每列代表一个特定的字母。对于每一行,我想加入 X 中值为 1 的那些字母。

例如:

import numpy as np
abc = np.array(['A','B','C','D','E','F'],dtype=str)
X = np.random.randint(0,2,(5,abc.shape[0]))

res = [np.string_.join('',abc[row==1]) for row in X]

这很好,只是这个特定任务是我的代码的瓶颈。因此,我尝试将其转移到 cython 但没有成功,这很大程度上是由于我对字符串和字符等的理解非常有限。下面的代码可供引用,但它很糟糕。这一次,它并没有完全返回我想要的结果(例如,字符必须转换为 Python 字符串),而且更令人担忧的是,我相信代码并不稳定。

import numpy as np
cimport numpy as np
cimport cython 

from libc.stdlib cimport malloc, free 

def join_c(int[:,:] idx, bytes abc):

    cdef:
        size_t i, j, count
        int n = idx.shape[0]
        int m = idx.shape[1]

        char *arr = <char *>malloc((n*(m+1))*sizeof(char))

    count = 0
    try:        
        for i in range(n):
            for j in range(m):
                if idx[i,j] == 1:

                    arr[count] = abc[j]
                    count +=1 

            arr[count] = ','
            count+=1

        return [x for x in arr]

    finally:
        free(arr)   

我想看看如何在 cython 中做到这一点,但我对任何其他快速解决方案感到满意。

最佳答案

这是一个基于字符串数组的解决方案 -

def join_singlechars(abc, X):
    # Get mask
    mask = X==1

    # Get start, stop indices for splitting the concatenated string later on
    idx = np.r_[0,mask.sum(1).cumsum()]

    # Get concatenated string
    n = idx[-1] #sum of 1s in mask          
    s = np.broadcast_to(abc, X.shape)[mask].tostring()
    # Or np.broadcast_to(abc, X.shape)[mask].view('S'+str(n))[0]

    return [s[i:j] for i,j in zip(idx[:-1],idx[1:])] # finally split

示例运行 -

In [229]: abc
Out[229]: array(['A', 'B', 'C', 'D', 'E', 'F'], dtype='|S1')

In [230]: X
Out[230]: 
array([[1, 0, 1, 0, 0, 1],
       [1, 1, 0, 1, 1, 0],
       [1, 0, 1, 1, 0, 0],
       [1, 1, 0, 1, 1, 1],
       [1, 1, 1, 0, 0, 1]])

In [231]: join_singlechars(abc, X)
Out[231]: ['ACF', 'ABDE', 'ACD', 'ABDEF', 'ABCF']

大型 5000 x 5000 阵列案例的计时 -

In [321]: abc = np.array(['A','B','C','D','E','F'],dtype=str)
     ...: abc = np.resize(abc,5000)
     ...: np.random.seed(0)
     ...: X = np.random.randint(0,2,(5000,5000))

In [322]: %timeit [np.string_.join('',abc[row==1]) for row in X]
1 loop, best of 3: 648 ms per loop

In [323]: %timeit join_singlechars(abc, X)
1 loop, best of 3: 209 ms per loop

关于python - 字符串的快速串联,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51828755/

相关文章:

python - 在 AWS Code Pipeline 中使用 docker compose 时出错

jquery - 突出显示字符串中的单词

c - 无法在 C 中按字母顺序对字符串列表进行排序

python - 如何从 Pandas 邻接矩阵数据帧创建有向网络图?

python - 如何获取多个未定义列不为空的 pandas DataFrame 的第一个索引?

python - 根据列对数据帧进行 Argsort

python - Django Wsgi ModuleNotFoundError : No module named 'project_name'

python - “模块”对象没有属性 'lru_cache'

java - 如何在java中用变量而不是硬编码数字在%s内字符串填充

python - 找到非有限值的最快方法