2012-12-30 14 views
8
map1 = containers.Map({'212','2','12','44'},[4,5,6,7]); 
keyset = str2double(keys(map1)); 

Jetzt mache ich eine Reihe von Operationen auf dem Keyset, die zurückMatlab: Konvertieren eines Doppel-Vektor-Array String Zellenfeld

Keyset= [203,2,12,39]; 

ich müde folgendes geben:

num2cell(num2str(keyset)); 
num2cell(num2str(keyset,1)); 
num2cell(num2str(keyset,'%11.0g')); 
num2cell(num2str(keyset,3)); 

All das gab im letzten Zellenfeld seltsame Ergebnisse. Ich brauche nur die Ganzzahlen, die als Schlüssel für eine andere Container-Map verwendet werden.

+2

Also, was ist das gewünschte Ergebnis? Ist es {203}, 2, 12, 39}? –

Antwort

13

Ich schlage vor, 5 zusätzliche Lösungen, von denen drei 4-5x schneller um als die bisher vorgeschlagenen Lösungen. Die Lehren daraus gelernt sind:

  • num2str langsam
  • cellfun und arrayfun erheblichen Aufwand hinzufügen können
  • Es gibt viele Möglichkeiten, um ein numerisches Array an eine Zelle Array von Strings zu konvertieren.

Die drei leistungsstärksten Lösungen sind sehr ähnlich in Bezug auf Leistung:

Looping Zellelemente

n4 = length(Keyset); 
tmp4 = cell(n4,1); 
for i4 = 1:n4 
    tmp4{i4} = sprintf('%i',Keyset(i4)); 
end 

Konvertieren alle Streich- und ruft textscan

tmp6 = textscan(sprintf('%i\n',Keyset'),'%s'); 
tmp6 = tmp6{1}; 

zuweisen Konvertiert alle in eine Zeichenfolge und ruft regexp auf.

tmp3 = regexp(sprintf('%i ',Keyset),'(\d+)','match'); 

Hier ist der vollständige Testcode mit Timings:

function t = speedTest 

t=zeros(7,1); 
for ii=1:100, 
    Keyset=randi(1,10,100); % random keys 
    tic; 
    eval([ 'tmp1 = { ', sprintf(' %d ', Keyset), ' }; ']); 
    t(1)=t(1)+toc; 
    tic; 
    tmp2=arrayfun(@num2str, Keyset, 'Uniform', false); 
    t(2)=t(2)+toc; 

    tic; 
    tmp3 = regexp(sprintf('%i ',Keyset),'(\d+)','match'); 
    t(3) = t(3)+toc; 

    tic; 
    n4 = length(Keyset); 
    tmp4 = cell(n4,1); 
    for i4 = 1:n4 
     tmp4{i4} = sprintf('%i',Keyset(i4)); 
    end 
    t(4) = t(4)+toc; 

    tic; 
    n5 = length(Keyset); 
    tmp5 = cell(n5,1); 
    for i5 = 1:n5 
     tmp4{i5} = num2str(Keyset(i5)); 
    end 
    t(5) = t(5)+toc; 

    tic; 
    tmp6 = textscan(sprintf('%i\n',Keyset'),'%s'); 
    tmp6 = tmp6{1}; 
    t(6) = t(6)+toc; 

    tic; 
    tmp7 = num2cell(Keyset); 
    tmp7 = cellfun(@(x)sprintf('%i',x),tmp7,'uni',false); 
    t(7) = t(7)+toc; 


end; 
t 

t = 

    1.7820 
    21.7201 
    0.4068 
    0.3188 
    2.2695 
    0.3488 
    5.9186 
+0

+1 für die 'regexp' Lösung und die Details! – Shai

+0

Yay, meins ist das langsamste! Aber wie haben wir hier über Leistung gesprochen? :-) –

+0

@EitanT: Es war nicht ich! Es war Shai, der damit angefangen hat. – Jonas

3

Wie sei:

eval([ 'NewKeySetStr = { ', sprintf(' %d ', Keyset), ' }; ']); 
NewKeySetStr 

Ich bin nicht sicher, dies die eleganteste Art und Weise ist, um die gewünschten Ergebnisse zu erzielen, aber es scheint zu funktionieren ...

Vergleich Laufzeit mit Eitan Lösung:

t=zeros(2,1); 
for ii=1:100, 
    Keyset=randi(1,10,100); % random keys 
    tic; 
    eval([ 'NewKeySetStr = { ', sprintf(' %d ', Keyset), ' }; ']); 
    t(1)=t(1)+toc; 
    tic; 
    tmp=arrayfun(@num2str, Keyset, 'Uniform', false); 
    t(2)=t(2)+toc; 
end; 
t 

Ausbeuten:

t = 
    0.3986 
    2.2527 

Es scheint, als wäre die vorgeschlagene Lösung schneller.

Hinweis: Es scheint, dass die aktuelle Implementierung von cellfun nicht für die Geschwindigkeit optimiert ist. Es wird gemunkelt, dass Mathworks in zukünftigen Versionen eine bessere Implementierung von cellfun einführen möchte. Daher ist Eitans Lösung in der aktuellen Version möglicherweise nicht optimal, aber es scheint eine gute Übung für Matlab-Fähigkeiten zu sein.

+0

+1: Obwohl Ihre Lösung "eval" verwendet, ist es immer noch schnell. Ich frage mich jedoch, ob es für sehr große Arrays funktioniert. Übrigens glaube ich, dass "0.3s" sich von "2.2s" um ca. eine Größenordnung (nicht zwei). –

+0

@EitanT - oops. korrigiert. – Shai

+0

Es ist sehr schwierig, Ihnen keine -1 für eine "böse" Lösung zu geben. Zum Glück gibt es mindestens 3 Lösungen, die schneller sind. – Jonas

7

Wie sei:

arrayfun(@num2str, Keyset, 'Uniform', false)' 

, die einen 4-für-1-Zellen-Array für Ihr Beispiel ergeben soll:

ans = 
    '203' 
    '2' 
    '12' 
    '39' 
+0

siehe meine bearbeitete Antwort. Vielen Dank. – Shai

+0

@Shai nicht sicher, dass das OP in diesem Fall nach Leistung sucht. –

+0

Deshalb habe ich die "Notiz" am unteren Rand hinzugefügt - Ihre Lösung ist mehr "Matlab" ish als meins, aber zu geringen Kosten der Laufzeit ... – Shai

0

herausgefunden, wie die regexp-Lösung für große Zahlen zu verbessern, mit der Split-Funktionalität. Auch wurde ich durch eine von Jonas Lösungen, die nicht alle Sprintf-Aufrufe in der for-Schleife ausgewertet hat, etwas in die Irre geführt. Edit: auch die neue 2016 String-Funktionalität in den Kommentaren vorgeschlagen hinzugefügt.

t = speedTest() 

function t = speedTest 

t=zeros(5,1); 
for ii=1:100 
    Keyset=randi(10000000,10,1000); % random keys 

    tic; 
    n4 = numel(Keyset); % changed to numel (length only gives number of columns) 
    tmp1 = cell(n4,1); 
    for i4 = 1:n4 
     tmp1{i4} = sprintf('%i',Keyset(i4)); 
    end 
    t(1) = t(1)+toc; 

    tic; 
    tmp2 = regexp(sprintf('%i ',Keyset),'(\d+)','match'); 
    t(2) = t(2)+toc; 

    tic; 
    tmp3 = regexp(sprintf('%i ',Keyset),' ','split'); 
    tmp3(end) = []; 
    t(3) = t(3)+toc; 

    tic; 
    tmp4 = string(Keyset(:)); 
    t(4) = t(4)+toc; 

    # test in case you want to go back to characters 
    tic; 
    tmp5 = char(string(Keyset(:))); 
    t(5) = t(5)+toc; 
end 
end 

Die regexp Lösung mit etwas besseren Leistung Split Ausbeuten und der String-Methode ist noch schneller:

t = 

    6.1916 
    1.1292 
    0.8962 
    0.6671 
    0.7523 
+0

Ab 16b hat MATLAB einen String-Datentyp. String (Keyset) ist ~ 25% schneller als Ihr schneller Fall. – matlabbit

+1

Mein erstes Experiment benutzte tmp4 = string (Keyset), was zur Zerstörung des vorhandenen tmp4 führte. Wenn Sie eine neue Variable verwenden, ist die Zeichenfolge (Keyset) 40% schneller als die schnellste. – matlabbit

Verwandte Themen