Matlab整数字符串解码...速度优化

时间:2017-11-13 11:54:22

标签: string matlab performance

我有以下问题:

我需要解码整数序列" c"字符串消息" m"通过以下关联:

  numpos = 10 % ( = size(c,2)/2)
  c = [3 4 1 1 4 2 5 2 3 3,1 1 1 1 2 2 2 3 3 3]

每一行" c"表示2 * numpos整数,其中第一个numpos参数编码位置

types = {'a' 'b@2' 'c@6' 'd@10' 'e@11'} 
仅当类型包含字符' @'时才应用

和第二个numpos参数。像这样:

  m = ' c:1@6 d:1@10 a a d:2@10 b:2@2 e:2@11 b:3@2 c:3@6 c:3@6' 

我目前的解决方案如下:

  function m = c2m(c,types)

  numpos = size(c,2)/2;

  F = cellfun(@(f) [' ' f], strrep(types,'@',':%d@'),'unif',0);
  m = arrayfun(@(f,k) sprintf(f{1},k),F(c(:,1:numpos)),c(:,numpos+(1:numpos)),'unif', 0);
  m = arrayfun(@(i) horzcat(m{i,:}), (1:numlines)', 'unif', 0)

  end

,测试代码如下:

  numlines = 10;
  c = repmat([3 4 1 1 4 2 5 2 3 3,1 1 1 1 2 2 2 3 3 3],numlines,1);
  types = {'a' 'b@2' 'c@6' 'd@10' 'e@11'};

  m = c2m(c,types);

  m =

    10×1 cell array

      {' c:1@6 d:1@10 a a d:2@10 b:2@2 e:2@11 b:3@2 c:3@6 c:3@6'}
      {' c:1@6 d:1@10 a a d:2@10 b:2@2 e:2@11 b:3@2 c:3@6 c:3@6'}
      {' c:1@6 d:1@10 a a d:2@10 b:2@2 e:2@11 b:3@2 c:3@6 c:3@6'}
      {' c:1@6 d:1@10 a a d:2@10 b:2@2 e:2@11 b:3@2 c:3@6 c:3@6'}
      {' c:1@6 d:1@10 a a d:2@10 b:2@2 e:2@11 b:3@2 c:3@6 c:3@6'}
      {' c:1@6 d:1@10 a a d:2@10 b:2@2 e:2@11 b:3@2 c:3@6 c:3@6'}
      {' c:1@6 d:1@10 a a d:2@10 b:2@2 e:2@11 b:3@2 c:3@6 c:3@6'}
      {' c:1@6 d:1@10 a a d:2@10 b:2@2 e:2@11 b:3@2 c:3@6 c:3@6'}
      {' c:1@6 d:1@10 a a d:2@10 b:2@2 e:2@11 b:3@2 c:3@6 c:3@6'}
      {' c:1@6 d:1@10 a a d:2@10 b:2@2 e:2@11 b:3@2 c:3@6 c:3@6'}

代码对我来说仍然太慢,我正在寻找任何加速。在这种情况下,CPU时间的最重要部分用于内置函数" sprintf"。

典型的实际问题是:

   numpos ~ 30 ... 60
   numlines ~ 1e4 ... 1e5

有什么想法吗?

3 个答案:

答案 0 :(得分:2)

在16b中,MATLAB发布了一些新的文本函数,使这很容易。同样在16b中,MATLAB提供了新的字符串数据类型,使其更快。

 function m = c2m_new(c,types, numlines)

     types = string(types);

     num_values = size(c,2)/2;

     a = c(:,1:num_values);
     b = c(:,(num_values+1):end);

     m = types(a);
     m = insertBefore(m,"@", ":" + b);
     m = join(m,2);
 end

>> numlines = 10;
>> c = repmat([3 4 1 1 4 2 5 2 3 3,1 1 1 1 2 2 2 3 3 3],numlines,1);
>> types = {'a' 'b@2' 'c@6' 'd@10' 'e@11'};
>> c2m_new(c,types,numlines)

ans = 

  10×1 string array

    "c:1@6 d:1@10 a a d:2@10 b:2@2 e:2@11 b:3@2 c:3@6 c:3@6"
    "c:1@6 d:1@10 a a d:2@10 b:2@2 e:2@11 b:3@2 c:3@6 c:3@6"
    "c:1@6 d:1@10 a a d:2@10 b:2@2 e:2@11 b:3@2 c:3@6 c:3@6"
    "c:1@6 d:1@10 a a d:2@10 b:2@2 e:2@11 b:3@2 c:3@6 c:3@6"
    "c:1@6 d:1@10 a a d:2@10 b:2@2 e:2@11 b:3@2 c:3@6 c:3@6"
    "c:1@6 d:1@10 a a d:2@10 b:2@2 e:2@11 b:3@2 c:3@6 c:3@6"
    "c:1@6 d:1@10 a a d:2@10 b:2@2 e:2@11 b:3@2 c:3@6 c:3@6"
    "c:1@6 d:1@10 a a d:2@10 b:2@2 e:2@11 b:3@2 c:3@6 c:3@6"
    "c:1@6 d:1@10 a a d:2@10 b:2@2 e:2@11 b:3@2 c:3@6 c:3@6"
    "c:1@6 d:1@10 a a d:2@10 b:2@2 e:2@11 b:3@2 c:3@6 c:3@6"

观察表现:

>> numlines = 1E4;
>> c = repmat([3 4 1 1 4 2 5 2 3 3,1 1 1 1 2 2 2 3 3 3],numlines,1);
>> types = {'a' 'b@2' 'c@6' 'd@10' 'e@11'};

% My solution
>> tic; for i = 1:10; c2m_new(c,types, numlines); end; toc
Elapsed time is 0.669311 seconds.

% michalkvasnicka's solution
>> tic; for i = 1:10; c2m(c,types, numlines); end; toc
Elapsed time is 23.643991 seconds.

% gnovice's solution
>> tic; for i = 1:10; c2m_gnovice(c,types, numlines); end; toc
Elapsed time is 8.960392 seconds.

答案 1 :(得分:0)

这是一个开始尝试的想法。

from tkinter import *

class main(Frame):
   def __init__(self, master=None):
       super(main, self).__init__(master)    
       self.grid()
       self.pack()
   def buttons_dash():
      # create first button
       self.bttn1_dash = Button(self, text = "Student Login",)
       self.bttn1_dash.grid()
       self.bttn1_dash.config(height=3, width=30)

       # create second button
       self.bttn2_dash = Button(self)
       self.bttn2_dash.grid()   
       self.bttn2_dash.configure(text = "Staff Login")
       self.bttn2_dash.config(height=3, width=30)

       # create third button
       self.bttn3_dash = Button(self)
       self.bttn3_dash.grid()
       self.bttn3_dash["text"] = "Exit"
       self.bttn3_dash.config(height=3, width=30)
       self.bttn3_dash = Button(self, text= "Exit")

class student_dashboard(Frame):
      def __init__(self, master=None):
       super(main, self).__init__(master)    
       self.grid()
       self.pack()
      def buttons_student():
       #create first button
       self.bttn1_student = Button(self, text = "View Highscores")
       self.bttn1_student.grid()
       self.bttn1_student.config(height=3, width=30)

       # create second button
       self.bttn2_student = Button(self)
       self.bttn2_student.grid()    
       self.bttn2_student.configure(text = "Save Score")
       self.bttn2_student.config(height=3, width=30)

# main
root = Tk()
root.title("Dashboard")
app = main(root)
root.mainloop()

然后

numpos = 10 % ( = size(c,2)/2)
c = [3 4 1 1 4 2 5 2 3 3,1 1 1 1 2 2 2 3 3 3];
types = {'a' 'b@2' 'c@6' 'd@10' 'e@11'} 

给出了

  

m =     1×10单元阵列     第1至10栏

     

{'c:1 @ 6'} {'d:1 @ 10'} {'a:1 @ 0'} {'a:1 @ 0'} {'d:2 @ 10'} {' b:2 @ 2'} {'e:2 @ 11'} {'b:3 @ 2'} {'c:3 @ 6'} {'c:3 @ 6'}

答案 2 :(得分:0)

这是您c2m功能的替代方案,比上面列出的numposnumlines的典型范围快2至3倍:

function m = c2m(c, types)
  numpos = size(c, 2)/2;
  [pre, post] = strtok(types(c(:, 1:numpos)), '@');
  mid = strsplit(sprintf(' :%i', 1:max(max(c(:, numpos+1:2*numpos)))));
  mid = mid(c(:, numpos+1:2*numpos).*~cellfun(@isempty, post)+1);
  m = cellstr(char(join(strcat(pre, mid, post))));
end

首先,使用strtokc分割'@'的前半部分。然后创建包含字符串mid的单元格数组{'' ':1' ':2' ... ':N'},其中Nc的后半部分中找到的最大值。这允许我们通过简单地索引到mid以获取字符串来避免应用于整个矩阵的昂贵转换函数(如sprintfnum2strint2str等)想。索引只是c的右半部分乘以表示'@'是否存在的逻辑数组(使用cellfun获得)并递增1。

最后,使用strcat连接三个不同的字符串(premidpost),使用join逐行收集到字符串中(自R2016b起出现),然后转换为具有cellstrchar的字符数组的单元格数组。

使用以下值对其进行测试:

numpos = 10;
numlines = 10;
c = repmat([3 4 1 1 4 2 5 2 3 3,1 1 1 1 2 2 2 3 3 3], numlines, 1);
types = {'a' 'b@2' 'c@6' 'd@10' 'e@11'};

我们得到了理想的结果:

m =

  10×1 cell array

    'c:1@6 d:1@10 a a d:2@10 b:2@2 e:2@11 b:3@2 c:3@6 c:3@6'
    'c:1@6 d:1@10 a a d:2@10 b:2@2 e:2@11 b:3@2 c:3@6 c:3@6'
    'c:1@6 d:1@10 a a d:2@10 b:2@2 e:2@11 b:3@2 c:3@6 c:3@6'
    'c:1@6 d:1@10 a a d:2@10 b:2@2 e:2@11 b:3@2 c:3@6 c:3@6'
    'c:1@6 d:1@10 a a d:2@10 b:2@2 e:2@11 b:3@2 c:3@6 c:3@6'
    'c:1@6 d:1@10 a a d:2@10 b:2@2 e:2@11 b:3@2 c:3@6 c:3@6'
    'c:1@6 d:1@10 a a d:2@10 b:2@2 e:2@11 b:3@2 c:3@6 c:3@6'
    'c:1@6 d:1@10 a a d:2@10 b:2@2 e:2@11 b:3@2 c:3@6 c:3@6'
    'c:1@6 d:1@10 a a d:2@10 b:2@2 e:2@11 b:3@2 c:3@6 c:3@6'
    'c:1@6 d:1@10 a a d:2@10 b:2@2 e:2@11 b:3@2 c:3@6 c:3@6'