MATLAB'da harita işlevi?


100

MATLAB'ın bir Harita işlevine sahip olmamasına biraz şaşırdım, bu yüzden onsuz yaşayamayacağım bir şey olduğu için bir tanesini kendim kırdım. Orada daha iyi bir versiyon var mı? MATLAB için eksik olduğum bir şekilde standart bir işlevsel programlama kitaplığı var mı?

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

kullanım örneğin olacaktır

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

12
Diğer dillerden Matlab'a giden 1. Ders: Döngüler için kullanmayın, bunlar vektörleştirilmiş bir çözümden birkaç kat daha yavaştır.
CookieOfFortune

15
JIT'in tanıtılmasıyla, çünkü döngüler bir zamanlar yaptıkları cezayı almayın.
MatlabDoug

@CookieOfFortune Bunun artık doğru olmadığını düşünüyorum ...
Ander Biguri

2
@AnderBiguri Bazı iyileştirmeler eklediklerini düşünüyorum ama yine de çok daha yavaş.
CookieOfFortune

Fonksiyonel Kütüphane Dosya Exchange etti map, foldl(olarak da bilinir reduce), select(aka filter) ve diğer vazgeçilmez öğeler. Önerilen (Matlab kullanmanız gerekiyorsa).
Ahmed Fasih

Yanıtlar:


133

Kısa cevap: yerleşik işlev arrayfun, mapişlevinizin sayısal diziler için yaptığını tam olarak yapar:

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

     1     4     9    16    25    36    49    64    81   100

Benzer şekilde davranan iki yerleşik işlev daha vardır: cellfun(hücre dizilerinin öğeleri üzerinde çalışan) ve structfun(bir yapının her alanında çalışan).

Bununla birlikte, özellikle eleman bazlı aritmetik operatörleri kullanarak vektörleştirmeden yararlanırsanız, bu işlevler genellikle gerekli değildir . Verdiğiniz örnek için, vektörleştirilmiş bir çözüm şöyle olacaktır:

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

     1     4     9    16    25    36    49    64    81   100

Bazı işlemler, öğeler arasında otomatik olarak çalışır (bir vektöre skaler bir değer eklemek gibi), diğerlerinde ise öğe bazlı işlem için özel bir sözdizimi vardır (bir . operatörden önce ). MATLAB'daki birçok yerleşik işlev, öğe bazlı işlemler (genellikle belirli bir boyuta uygulanır, örneğin sumve meanörneğin) kullanarak vektör ve matris argümanları üzerinde çalışmak üzere tasarlanmıştır ve bu nedenle harita işlevleri gerektirmez.

Özetlemek gerekirse, burada bir dizideki her bir öğenin karesini almanın bazı farklı yolları vardır:

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

Elbette, bu kadar basit bir işlem için 1. seçenek en mantıklı (ve etkili) seçimdir.


2
Birinci seçeneğin sadece daha basit değil, aynı zamanda daha hızlı olduğu da unutulmamalıdır (seçenek 3'e kıyasla, 2, 1'e çok benzer olmalıdır)!
Diederick C.Niehorster

10

Vektör ve öğe bazlı işlemlere ek olarak, cellfunhücre dizileri üzerinde eşleme işlevleri de vardır . Örneğin:

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

'UniformOutput' doğruysa (veya sağlanmadıysa), sonuçları hücre dizisinin boyutlarına göre birleştirmeye çalışacaktır.

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

2

Matlab'ın vektörleştirmesini kullanarak oldukça basit bir çözüm şöyle olacaktır:

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

Şimdi yazıyorum

c( b ) = a

İadeler

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

c (b), b ile verilen endekslerde c'nin elemanlarıyla 5 boyutlu bir vektöre referanstır. Şimdi, bu referans vektörüne değer atarsanız, c (b) c'deki değerlere referanslar içerdiği ve kopya içermediği için c'deki orijinal değerlerin üzerine yazılır.


1

Görünen o ki, gerekli sonuç bir işlev dizisi ise yerleşik array çalışmıyor: örneğin: map (@ (x) [xx ^ 2 x ^ 3], 1: 10)

Aşağıdaki küçük modlar bunun daha iyi çalışmasını sağlar:

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 , örneğiniz için işe yarar..., 'UniformOutput', false); , dizilerinizi içeren bir hücre dizisi çıkışı oluşturmak için giriş bağımsız değişkenlerini dahil etmeniz, ardından bunları istediğiniz gibi biçimlendirip hücre dışı bir dizide birleştirmeniz gerekir.
gnovice

0

Matlab'ın yerleşik bir harita işlevi yoksa, bunun nedeni verimlilik hususları olabilir. Uygulamanızda, genellikle matlab dünyasında hoş karşılanmayan listenin öğelerini yinelemek için bir döngü kullanıyorsunuz. Yerleşik matlab işlevlerinin çoğu "vektörleştirilmiştir", yani tüm bir dizide bir işlevi çağırmak, onun üzerinde kendi başınıza yinelemekten ve her öğe için işlevi çağırmaktan daha etkilidir.

Başka bir deyişle, bu


a = 1:10;
a.^2

bundan çok daha hızlı


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

harita tanımınızı varsayarsak.


2
Sanırım amacı, onun ille de döngüye girmesini istemesi değil, sadece sonuç olarak sağlanan fonksiyonun sağlanan dizinin karşılık gelen elemanlarına uygulanmasının sonuç dizisine sahip olarak belirtilmesiydi. Matlab hakkında pek bir şey bilmiyorum ama görünüşe göre bu işi arrayfun yapıyor.

1
Çoğu yerleşik Matlab işlevi ve operatörü bunu zaten yapar: giriş dizisinin her bir öğesi üzerinde çalışırlar ve karşılık gelen bir sonuç dizisi döndürürler.
Dima

0

Buna gerek yok mapdeğerleri listesini uygulanan bir skaler fonksiyon değerlerinin her birine uygulanmış ve dolayısıyla benzer şekilde çalışır, çünkü map. Sadece dene

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

f(l)

Özel durumda yazabilirsin

l.^2

9
-1: Bu aslında doğru değil. Matlab, skaler işlevleri belirtecek kadar güçlü bir tür sistemine sahip değildir. f, vektörle çağrılır ve örneğinizde tek bir vektör toplama işlemi gerçekleştirilir. Bunu doğrulamak için, kod örneğinizin profilini çıkarın (kodu çalıştırmadan önce "profil açık", ardından "raporu kapat"). F'ye tek bir çağrı olduğunu göreceksiniz.
Bay Fooz

-1

Çözümü önceki cevaplarda açıklandığı gibi vektörleştirmek, hız için muhtemelen en iyi çözümdür. Vectorizing aynı zamanda çok Matlaby ve iyi hissettiriyor.

Bununla birlikte, Matlab'ın artık bir Harita kapsayıcı sınıfı var.

Bkz. Http://www.mathworks.com/help/matlab/map-containers.html


Op, cellfunkarma tablolardan veya anahtar-değer çiftlerinden değil , üst düzey işlevden bahsediyor, yani ve diğerleri.
Ahmed Fasih
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.