在python中无序排列字符串数据

2024-10-02 02:23:47 发布

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

我有一列有一千万个字符串。字符串中的字符需要以某种方式重新排列。你知道吗

原始字符串:AAA01188P001

乱序字符串:188A1A0AP001

现在我运行了一个for循环,它接受每个字符串并重新定位每个字母,但这需要几个小时才能完成。有没有更快的方法来达到这个结果?你知道吗

这是for循环。你知道吗

for i in range(0, len(OrderProduct)):
    s = list(OrderProduct['OrderProductId'][i])
    a = s[1]
    s[1] = s[7]
    s[7] = a 
    a = s[3]
    s[3] = s[6]
    s[6] = a 
    a = s[2]
    s[2] = s[3]
    s[3] = a 
    a = s[5]
    s[5] = s[0]
    s[0] = a 
    OrderProduct['OrderProductId'][i] = ''.join(s)

Tags: 方法字符串in定位forlen字母方式
3条回答

我用不同的方法做了一些性能测试:

以下是我得到的1000000次洗牌的结果:

188A1AA0P001 usefString 0.518183742
188A1AA0P001 useMap     1.415851829
188A1AA0P001 useConcat  0.5654986979999999
188A1AA0P001 useFormat  0.800639699
188A1AA0P001 useJoin    0.5488918539999998

基于此,带有硬编码子字符串的格式字符串似乎是最快的。你知道吗

下面是我用来测试的代码:

def usefString(s): return f"{s[5:8]}{s[0]}{s[4]}{s[1:4]}{s[8:]}"

posMap = [5,6,7,0,4,1,2,3,8,9,10,11]
def useMap(s): return "".join(map(lambda i:s[i], posMap))

def useConcat(s): return s[5:8]+s[0]+s[4]+s[1:4]+s[8:]

def useFormat(s): return '{}{}{}{}{}'.format(s[5:8],s[0],s[4],s[1:4],s[8:])

def useJoin(s): return "".join([s[5:8],s[0],s[4],s[1:4],s[8:]])

from timeit import timeit
count = 1000000
s = "AAA01188P001"

t = timeit(lambda:usefString(s),number=count)
print(usefString(s),"usefString",t)

t = timeit(lambda:useMap(s),number=count)
print(useMap(s),"useMap",t)

t = timeit(lambda:useConcat(s),number=count)
print(useConcat(s),"useConcat",t)

t = timeit(lambda:useFormat(s),number=count)
print(useFormat(s),"useFormat",t)

t = timeit(lambda:useJoin(s),number=count)
print(useJoin(s),"useJoin",t)

性能:(由@jezrael添加)

N = 1000000
OrderProduct = pd.DataFrame({'OrderProductId':['AAA01188P001'] * N})

In [331]: %timeit [f'{s[5:8]}{s[0]}{s[4]}{s[1:4]}{s[8:]}' for s in OrderProduct['OrderProductId']]
527 ms ± 16.7 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

In [332]: %timeit [s[5:8]+s[0]+s[4]+s[1:4]+s[8:] for s in OrderProduct['OrderProductId']]
610 ms ± 18.8 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

In [333]: %timeit ['{}{}{}{}{}'.format(s[5:8],s[0],s[4],s[1:4],s[8:]) for s in OrderProduct['OrderProductId']]
954 ms ± 76.6 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

In [334]: %timeit ["".join([s[5:8],s[0],s[4],s[1:4],s[8:]]) for s in OrderProduct['OrderProductId']]
594 ms ± 10.5 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

如果逻辑是一致的,你能用切片重建字符串吗?你知道吗

s = OrderProduct['OrderProductId'][i]
new_s = s[5]+s[7]+s[1:2]+s[6]+s[4]+s[0]+s[3]+s[1]

或作为格式字符串:

new_s = '{}{}{}{}{}{}{}'.format(s[5],s[7]...)

编辑:+1代表Dave的“”建议。join()列表与串联。你知道吗

如果您只想洗牌字符串(没有特定的逻辑),可以通过以下几种方式进行:

使用字符串工具:

import string_utils
print string_utils.shuffle("random_string")

使用内置方法:

import random
str_var = list("shuffle_this_string")
random.shuffle(str_var)
print ''.join(str_var)

使用numpy:

import numpy
str_var = list("shuffle_this_string")
numpy.random.shuffle(str_var)
print ''.join(str_var)

但是,如果需要使用特定的逻辑(例如,将每个元素放置在特定的位置),可以执行以下操作:

s = 'some_string'
s = ''.join([list(s)[i] for i in [1,6,2,7,9,4,0,8,5,10,3]])
print(s)

输出:

otmrn_sisge

如果这仍然需要很长时间,可以使用多处理。像这样:

from multiprocessing import Pool
p = Pool(4) # 4 is the number of workers. usually is set to the number of CPU cores

def shuffle_str(s):
    # do shuffling here, and return


list_of_strings = [...]
list_of_results = p.map(shuffle_str, list_of_strings)

相关问题 更多 >

    热门问题