2009-06-11 6 views
85

私は、MATLABにマップ関数がないことに少し驚いています。だから私はそれが私がなければ生きられないものなので、私は一緒にハッキングしました。そこに良いバージョンがありますか? MATLAB用の多少標準的な関数型プログラミングライブラリがありますか?MATLABのマップ機能?

map(@(x)x^2,1:10) 
+11

レッスン#1を参照してください:ループのために使用しないでくださいを、彼らはベクトル化ソリューションよりも遅く数桁です。 – CookieOfFortune

+1

再帰はどうですか? – Dario

+15

JITの導入により、forループは以前に行ったペナルティを受けません。 – MatlabDoug

答えて

1

matlabにマップ機能が組み込まれていない場合は、効率を考慮する必要があります。あなたの実装では、リストの要素を繰り返し処理するためにループを使用していますが、これは一般的にMATLABの世界では嫌われています。ほとんどのビルトインMATLAB関数は "ベクトル化"されています。 e。配列全体に対して関数を呼び出す方が、自分自身で繰り返し処理し、各要素の関数を呼び出すよりも効率的です。言い換えれば

、この


a = 1:10; 
a.^2 

は、マップのあなたの定義を想定し、この


a = 1:10; 
map(@(x)x^2, a) 

よりもはるかに高速です。

+1

私は彼の要点は必ずしもループしたくないということではなく、指定された関数を供給された配列の対応する要素に適用した結果の配列を持つことで指定するだけであると思います。私は多くのMATLABを知らないが、それはarrayfunは仕事をしているようだ。 –

+1

組み込みのMatlabの関数と演算子は、すでに実装済みです。つまり、入力配列の各要素で動作し、結果の対応する配列を返します。 – Dima

123

短い答え:組み込み関数ARRAYFUNがあなたのマップ関数は数値配列の場合と正確に何が行われます。

>> y = arrayfun(@(x) x^2,1:10) 
y = 

    1  4  9 16 25 36 49 64 81 100 

同様に振る舞う他の二つの組み込み関数があります。CELLFUN(動作セル配列の要素上)およびSTRUCTFUN(構造体の各フィールドで機能します)。

ただし、ベクトル化を利用する場合は、特に要素ごとにarithmetic operatorsを使用すると、これらの関数は必要でないことがよくあります。あなたが与え例えば、ベクトル化ソリューションは、次のようになります。

>> x = 1:10; 
>> y = x.^2 
y = 

    1  4  9 16 25 36 49 64 81 100 

、他の事業者が付さ(要素ごとの操作のための特別な構文を持っていながら、一部の操作が自動的に(ベクトルのスカラー値を追加するなど)の要素間で動作しますオペレータの前に "。"を付けてください)。 MATLABの多くの関数は、要素単位の操作を使用してベクトル引数と行列引数を操作するように設計されているため、マップ関数は必要ありません。ここでは、要約すると

は、配列の各要素を二乗するためにいくつかの異なる方法があります。もちろん

x = 1:10;  %// Sample array 
f = @(x) x.^2; %// Anonymous function that squares each element of its input 

%// Option #1: 
y = x.^2; %// Use the element-wise power operator 

%// Option #2: 
y = f(x); %// Pass a vector to f 

%// Option #3: 
y = arrayfun(f,x); %// Pass each element to f separately 

、このような簡単な操作のために、オプション#1が最も賢明な選択です。

+2

オプション1は単純ではなく、高速です(オプション3と比較して、2は1に非常に似ているはずです)! –

0

mapの値のリストに適用されるスカラー関数が各値に適用されるため、mapと同様の働きをするため、mapは必要ありません。ちょうどあなたの特定のケースで

l = 1:10 
f = @(x) x + 1 

f(l) 

を試してみてください、あなたもベクトルと要素単位の演算に加えて

l.^2 
+9

-1:実際はそうではありません。 Matlabにはスカラー関数を指定するのに十分な型のシステムはありません。 fはベクトルと共に呼び出され、あなたの例では単一のベクトル加算が実行されます。これを確認するには、コードサンプル(コードを実行する前に "profile on"、その後に "profile off report")をプロファイルします。あなたはfへの単一の呼び出しがあることがわかります。 –

10

を書くことができ、cellfunは、セルアレイ上でマッピング機能のためにもあります。例えば:

cellfun(@upper, {'a', 'b', 'c'}, 'UniformOutput',false) 
ans = 
    'A' 'B' 'C' 

「UniformOutput」は(提供されるか、またはしない)が真である場合、それはそう

cellfun(@upper, {'a', 'b', 'c'}) 
ans = 
ABC 
3

かなり簡単な解決策は、セルアレイの大きさに応じて結果を連結しようとし、MATLABのベクトル化を使用すると、次のようになります。今

a = [ 10 20 30 40 50 ]; % the array with the original values 
b = [ 10 8 6 4 2 ]; % the mapping array 
c = zeros(1, 10); % your target array 

、入力

c(b) = a 

戻り

c = 0 50  0 40  0 30  0 20  0 10 

C(B)Bで与えられるインデックスで、Cの要素とサイズ5のベクトルへの参照です。ここで、この参照ベクトルに値を渡すと、c(b)にはcの値への参照とコピーがないので、cの元の値は上書きされます。

1

必要な結果が関数の配列である場合は、内蔵arrayfunが動作しないようです: 例: マップ(@(x)は[XX^X^3 2]を、1:10)

以下

わずかな改造は、より良い、この作業を行います。前回の回答で述べたよう

function results = map(f,list) 
% why doesn't MATLAB have a Map function? 
for k = 1:length(list) 
    if (k==1) 
     r1=f(list(k)); 
     results = zeros(length(r1),length(list)); 
     results(:,k)=r1; 
    else 
     results(:,k) = f(list(k)); 

    end; 
end; 
end 
+5

[ARRAYFUN](http://www.mathworks.com/help/techdoc/ref/arrayfun.html)はあなたの例ではうまくいくでしょう。入力引数 '...、 'UniformOutput'、false ); 'あなたの配列を含むセル配列の出力を作成し、それらをフォーマットして結合しますが、非セル配列にすることができます。 – gnovice

-1

は、ソリューションをベクトルスピードのために、おそらく最高のソリューションです。ベクトル化も非常にMatlabyで、気分が良いです。

これでMatlabにMapコンテナクラスが追加されました。

は、MATLABに他の言語から行くhttp://www.mathworks.com/help/matlab/map-containers.html

+0

オペレーションは、高次関数、すなわち、ハッシュテーブルまたはキー/値のペアではなく、「セルフン(cellfun)」など。 –