Matlab中高效字符串拼接

4

我之前偶然发现了这个文档。它评估了Python中几种字符串连接方法的性能。以下是其中比较的6种方法中的4种:

Python字符串连接方法

方法1:朴素的追加

def method1():
    out_str = ''
    for num in xrange(loop_count):
        out_str += `num`
    return out_str

方法四:构建字符串列表,然后连接它们

def method4():
  str_list = []
  for num in xrange(loop_count):
    str_list.append(`num`)
  return ''.join(str_list)

Method 5: Write to a pseudo file

def method5():
    from cStringIO import StringIO
    file_str = StringIO()
    for num in xrange(loop_count):
        file_str.write(`num`)
    return file_str.getvalue()

方法6: 列表推导式

def method6():
    return ''.join([`num` for num in xrange(loop_count)])

根据结果得出以下结论:

大多数实际程序中我会使用方法6。它快速且易于理解。但需要你能够编写单个表达式来返回每个要追加的值。有时这种方式并不方便,例如当有几个不同的代码块正在生成输出时。在这些情况下,可以在方法4和方法5之间选择。

阅读本文后,我意识到自己并不知道5和6两种方法。大多数情况下,我现在更喜欢使用方法5,因为它允许我像写文件一样写字符串。

我的问题是,matlab中的字符串连接有哪些不同的技术?我几乎不在matlab中处理字符串,但我遇到了一个需要我写字符串的问题。一种解决方案我想到的是写入临时文件,并在完成后读取该文件。但在这样做之前,我决定先问一下是否有更好的选项。现在,这里有一种天真的matlab追加方法:

Matlab 字符串连接方法

方法1:天真的追加

function out_str = method1(loop_count)
    out_str = '';
    for num=1:loop_count
       out_str = [out_str num2str(num)]; %#ok<AGROW>
    end
end

在Matlab中是否有类似于方法4、5和6的方法,我们可以用于效率比较?

编辑:

这里有一些类似于Python中的方法5(写入文件)的方法:

function out_str = method2(loop_count)
    fid = fopen('._tmpfile.tmp', 'w');
    for num=1:loop_count
        fprintf(fid, '%d', num);
    end
    fclose(fid);
    out_str = fileread('._tmpfile.tmp');
end

这是一个简单的测试:

>> tic; tmp1 = method1(100000); toc
Elapsed time is 13.144053 seconds.
>> tic; tmp2 = method2(100000); toc
Elapsed time is 2.358082 seconds.

你的 method1 实现可能因为使用了 num2str 而受到很大影响,尝试使用 sprintf('%d', num) 替代它。将数字转换为字符串与字符串连接分开处理可以获得更可靠的结果。 - erikced
@erikced,我在编辑后注意到了这一点。结果发现,如果我使用sprintf,那么method1method2更快。 - jmlopez
2个回答

2
由于Matlab倾向于在数组上执行向量化操作,并且使用for循环时效率低下,最好的通用解决方案是创建一个带有所有字符串的单元数组,并使用[str_array{:}]或根据您的需求使用strjoinsprintf进行组合。
对于某些操作,例如从数字数组创建逗号分隔字符串,还有更有效的解决方案。
numeric_array = rand(1 ,100000);
out_str = sprintf('%d,', numeric_array);
out_str = out_str(1:end-1);

由于它可以同时执行字符串转换和连接操作,因此它非常实用。

另外需要注意的是,在我的电脑上,使用Matlab 2013a时,out_str = sprintf('%s ', str_array{:});out_str = out_str(1:end-1)strjoin(str_array{:}) 快大约十倍。


2

通常有一种快速增长向量串联的方法,这并没有经常提到。以下是一个明确的示例(连接数字,但字符在matlab中也被视为数字):

%What you will typically find in sample code
loop_count=1e4
out_str = [];
tic
for num=1:loop_count
    out_str = [out_str num]; %#ok<AGROW>
end
toc

% What typically runs faster
out_str = [];
tic
for num=1:loop_count
    out_str(end+1) = num; 
end
toc

将会给予

Elapsed time is 0.077540 seconds.
Elapsed time is 0.004776 seconds.

当然,如果您在开始之前已经知道要连接的所有内容,那么游戏就会改变。假设您想要连接向量中数字的字符串表示形式:
%Vectorized code typically runs fastest
v =1:loop_count
M=[num2str(v)];
tic
M=M(~M==' ');
toc

将会给予

Elapsed time is 0.001903 seconds.

我认为对于一般目的来说,最快的方法是朴素的方法,即只需将字符串附加到字符串中。对于我正在处理的问题,我将创建一个字符串,其中不仅包含数字,还包含其他内容。现在,我有两个选择,我可以将要放入字符串中的所有信息存储在单元格中,然后将其更改为字符串,或者随着进展逐步将所有内容附加到单个字符串中。 - jmlopez
@jmlopez 如果您只一个接一个地获取值,我确实怀疑中间存储是否有所收益,很可能不会有太大的收益。但还有一件事需要考虑,那就是这些字符串是否真的需要一个一个地获取。如果不需要,那么可能有一些性能提升的余地。 - Dennis Jaheruddin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接