【问题标题】:Call sscanf with multiple strings使用多个字符串调用 sscanf
【发布时间】:2016-04-12 13:00:12
【问题描述】:

我想将日期字符串转换为数字矩阵,并且需要以非常高的速度进行。我的意见:

 dateStrings = [
     '2015 07 09 12 28 18.17641';
     '2015 07 09 12 28 19.17641';
     '2015 07 09 12 28 20.17641']

我现在想使用sscanf 将它们转换为数字。 (原因是它非常快)。如果 dateStrings 只包含 1 个字符串,这很好用,但在这种情况下,我有 3 个字符串。 (实际上超过 50 000)。

sscanf(dateStrings, '%d %d %d %d %d %f')

所需的输出是一个如下所示的矩阵:

 2015            7            9           12           28       18.176
 2015            7            9           12           28       19.176
 2015            7            9           12           28       20.176

有什么方法可以使用多个字符串对 sscanf 进行调用,还是我必须进行循环?

欢迎任何关于如何解决问题的建议,只要速度快!


编辑:Suever 的解决方案给了我很多速度!但是,上述输入并非真正正确。实际输入如下所示。既然您提到使用单元格实际上更快,您将如何使用此输入?目前,我使用cell2mat 转换输入,然后用空格替换某些索引以结束字符串,例如:'2015 07 09 12 28 18.17641'

Input is 4x1 cell:

    '2015-11-18T23:31:49.37486 +01:00'
    '2015-11-18T23:31:49.37583 +01:00'
    '2015-11-18T23:31:49.37658 +01:00'
    '2015-11-18T23:31:49.37735 +01:00'

【问题讨论】:

    标签: string matlab date matrix scanf


    【解决方案1】:

    二维字符数组特别难以操作。如果您首先使用 cellstr 将其转换为单元格,则使用起来会容易得多。

    C = cellstr(dateStrings);
    output = sscanf(sprintf('%s ', C{:}), '%f');
    output = reshape(output, [], numel(C)).';     %'
    
    %//  2015            7            9           12           28       18.176
    %//  2015            7            9           12           28       19.176
    %//  2015            7            9           12           28       20.176
    

    或者你可以使用cellfun

    output = cellfun(@(x)sscanf(x, '%f'), C, 'uni', 0);
    output = cat(2, output{:}).';
    

    您还可以使用str2numstrjoin 的组合。

    output = reshape(str2num(strjoin(C)), [], numel(C)).';
    

    老实说,循环访问您的初始数据可能是最快的选择。

    output = NaN(size(dateStrings,1), 6);
    for k = 1:size(dateStrings, 1);
        output(k,:) = sscanf(dateStrings(k,:), '%f');
    end
    

    我使用具有不同行数的输入对这些方法进行了基准测试,并得到了以下结果。第一个和第三个看起来性能最好。

    更新

    由于您最初的问题根本无法准确表示您的数据,因此您现在需要将格式说明符更改为 sscanf。您也可以直接传递您的输入元胞数组 (C),而不是使用 cellstr

    sscanf(x, '%d-%d-%dT%d:%d:%f +%*d:%*d')
    

    所以我们可以将它应用到上面的一些答案中:

    %// Option #1
    fmt = '%d-%d-%dT%d:%d:%f +%*d:%*d';
    output = reshape(sscanf(sprintf('%s ', C{:}), fmt), [], numel(C)).';   %'
    
    %// Option #2
    output = cellfun(@(x)sscanf(x, fmt), C, 'uni', 0);
    output = cat(2, output{:}).';   %'
    
    %// Option #4
    output = NaN(numel(C), 6);
    for k = 1:numel(C)
        output(k,:) = sscanf(C{k}, fmt);
    end
    

    【讨论】:

    • 非常好!使用第一个解决方案让我加快了很多速度。我编辑了我的问题,你对后半部分有什么意见吗?
    • @Goatcat 我已经更新了解决方案。下次发布实际数据是有益的。特别是当它需要解析时。
    • 哇!谢谢,史诗般的工作!在第一次测试中,您的解决方案快了 10 倍(使用选项 #1)。我永远感激不尽!
    • @Goatcat 如果答案解决了您的问题,请不要在 cmets 中提出其他问题或使用新要求更新问题。相反,请将答案标记为已接受并在单独的帖子中提出另一个问题。
    猜你喜欢
    • 2023-03-10
    • 1970-01-01
    • 1970-01-01
    • 2016-08-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多