Fungsi peta di MATLAB?

100

Saya sedikit terkejut bahwa MATLAB tidak memiliki fungsi Peta, jadi saya meretasnya sendiri karena itu adalah sesuatu yang saya tidak bisa hidup tanpanya. Apakah ada versi yang lebih baik di luar sana? Apakah ada pustaka pemrograman fungsional standar untuk MATLAB di luar sana yang saya lewatkan?

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

end

penggunaan akan misalnya

map( @(x)x^2,1:10)
Will Ness
sumber
12
Pelajaran # 1 beralih dari bahasa lain ke Matlab: Jangan gunakan untuk loop, mereka beberapa kali lipat lebih lambat daripada solusi vektor.
CookieOfFortune
15
Dengan diperkenalkannya JIT, untuk loop tidak mengambil penalti yang pernah mereka lakukan.
MatlabDoug
@CookieOfFortune Saya pikir itu tidak benar lagi ...
Ander Biguri
2
@AnderBiguri Saya pikir mereka telah menambahkan beberapa peningkatan tetapi masih jauh lebih lambat.
CookieOfFortune
The Library Fungsional File Exchange telah map, foldl(juga dikenal sebagai reduce), select(alias filter), dan barang sangat diperlukan lainnya. Disarankan (jika Anda harus menggunakan Matlab).
Ahmed Fasih

Jawaban:

133

Jawaban singkatnya: fungsi arrayfunbawaan melakukan persis seperti mapfungsi Anda untuk larik numerik:

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

     1     4     9    16    25    36    49    64    81   100

Ada dua fungsi bawaan lainnya yang berperilaku serupa: cellfun(yang beroperasi pada elemen larik sel) dan structfun(yang beroperasi pada setiap bidang struktur).

Namun, fungsi-fungsi ini seringkali tidak diperlukan jika Anda memanfaatkan vektorisasi, khususnya menggunakan operator aritmatika yang bijaksana . Untuk contoh yang Anda berikan, solusi vektorisasi adalah:

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

     1     4     9    16    25    36    49    64    81   100

Beberapa operasi akan secara otomatis beroperasi lintas elemen (seperti menambahkan nilai skalar ke vektor) sementara operator lain memiliki sintaks khusus untuk operasi elemen-bijaksana (dilambangkan dengan a .sebelum operator). Banyak fungsi bawaan di MATLAB dirancang untuk beroperasi pada argumen vektor dan matriks menggunakan operasi bijak-elemen (sering diterapkan pada dimensi tertentu, seperti sumdanmean misalnya), dan karenanya tidak memerlukan fungsi peta.

Untuk meringkas, berikut adalah beberapa cara berbeda untuk mengkuadratkan setiap elemen dalam sebuah array:

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

Tentu saja, untuk operasi sederhana seperti itu, opsi # 1 adalah pilihan yang paling masuk akal (dan efisien).

gnovice
sumber
2
Perlu dicatat bahwa opsi 1 tidak hanya lebih sederhana, tetapi juga lebih cepat (dibandingkan dengan opsi 3, 2 harus sangat mirip dengan 1)!
Diederick C. Niehorster
10

Selain operasi vektor dan elemen, ada juga cellfununtuk fungsi pemetaan melalui array sel. Sebagai contoh:

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

Jika 'UniformOutput' benar (atau tidak disediakan), itu akan mencoba untuk menggabungkan hasil sesuai dengan dimensi larik sel, jadi

cellfun(@upper, {'a', 'b', 'c'})
ans =
ABC
kwatford.dll
sumber
2

Solusi yang agak sederhana, menggunakan vektorisasi Matlab adalah:

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

Sekarang, mengetik

c( b ) = a

kembali

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

c (b) adalah referensi ke vektor berukuran 5 dengan elemen c pada indeks yang diberikan oleh b. Sekarang jika Anda memasukkan nilai ke vektor referensi ini, nilai asli di c ditimpa, karena c (b) berisi referensi ke nilai di c dan tidak ada salinannya.

dokter
sumber
1

Tampaknya arrayfun built-in tidak berfungsi jika hasil yang dibutuhkan adalah fungsi array: eg: map (@ (x) [xx ^ 2 x ^ 3], 1: 10)

sedikit mod di bawah membuat ini bekerja lebih baik:

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
Foo Bara
sumber
5
ARRAYFUN akan berfungsi untuk contoh Anda, Anda hanya perlu menyertakan argumen input ..., 'UniformOutput', false);untuk membuat output array sel yang berisi array Anda, lalu memformat dan menggabungkannya sesuai keinginan Anda ke dalam array non-sel.
gnovice
0

Jika matlab tidak memiliki fungsi map built in, bisa jadi karena pertimbangan efisiensi. Dalam implementasi Anda, Anda menggunakan loop untuk mengulangi elemen-elemen daftar, yang umumnya tidak disukai di dunia matlab. Sebagian besar fungsi matlab built-in adalah "vektorisasi", yaitu lebih efisien untuk memanggil fungsi pada seluruh larik, daripada mengulanginya sendiri dan memanggil fungsi untuk setiap elemen.

Dengan kata lain, ini


a = 1:10;
a.^2

jauh lebih cepat dari ini


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

dengan asumsi definisi Anda tentang peta.

Dima
sumber
2
Saya pikir maksudnya bukanlah bahwa dia ingin itu selalu berulang, tetapi hanya untuk ditentukan sebagai hasil dari larik hasil penerapan fungsi yang disediakan ke elemen yang sesuai dari larik yang disediakan. Saya tidak tahu banyak tentang matlab, tetapi tampaknya arrayfun melakukan pekerjaan itu.
1
Sebagian besar fungsi dan operator Matlab built-in sudah melakukannya: mereka beroperasi pada setiap elemen dari larik input, dan mengembalikan larik hasil yang sesuai.
Dima
0

Anda tidak perlu mapkarena fungsi skalar yang diterapkan ke daftar nilai diterapkan ke setiap nilai dan karenanya berfungsi serupa map. Coba saja

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

f(l)

Dalam kasus khusus Anda, Anda bahkan dapat menulis

l.^2
Dario
sumber
9
-1: Itu sebenarnya tidak benar. Matlab tidak memiliki sistem tipe yang cukup kuat untuk menentukan fungsi skalar. f disebut dengan vektor dan satu penjumlahan vektor dilakukan dalam contoh Anda. Untuk memverifikasi ini, buat profil contoh kode Anda ("profil aktif" sebelum menjalankan kode, lalu "profil nonaktifkan laporan" setelahnya). Anda akan melihat ada satu panggilan ke f.
Tuan Fooz
-1

Membuat vektor solusi seperti yang dijelaskan dalam jawaban sebelumnya mungkin merupakan solusi terbaik untuk kecepatan. Vektorisasi juga sangat Matlaby dan terasa menyenangkan.

Dengan itu Matlab sekarang memiliki kelas kontainer Map.

Lihat http://www.mathworks.com/help/matlab/map-containers.html

TallBrian
sumber
Op berbicara tentang fungsi tingkat tinggi, yaitu, cellfundkk., Bukan tabel hash atau pasangan nilai kunci.
Ahmed Fasih