ฟังก์ชั่นแผนที่ใน MATLAB?


100

ฉันแปลกใจเล็กน้อยที่ MATLAB ไม่มีฟังก์ชั่นแผนที่ดังนั้นฉันจึงแฮ็คเข้าด้วยกันเพราะมันเป็นสิ่งที่ฉันขาดไม่ได้ มีรุ่นที่ดีกว่านี้ไหม มีไลบรารีการเขียนโปรแกรมฟังก์ชันมาตรฐานสำหรับ MATLAB ที่ฉันขาดหายไปหรือไม่?

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

การใช้งานจะเป็นเช่น

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

12
บทเรียน # 1 เปลี่ยนจากภาษาอื่นไปเป็น Matlab: อย่าใช้สำหรับลูปเพราะเป็นคำสั่งขนาดเล็ก ๆ น้อย ๆ ที่ช้ากว่าโซลูชันแบบเวกเตอร์
CookieOfFortune

15
ด้วยการแนะนำ JIT สำหรับการวนซ้ำอย่ารับโทษที่เคยทำ
MatlabDoug

@CookieOfFortune ฉันคิดว่ามันไม่จริงอีกต่อไป ...
Ander Biguri

2
@AnderBiguri ฉันคิดว่าพวกเขาได้เพิ่มการปรับปรุงบางอย่างแล้ว แต่ก็ยังช้ากว่ามาก
CookieOfFortune

ห้องสมุดฟังก์ชั่นที่ File แลกเปลี่ยนได้map, foldl(ยังเป็นที่รู้จักreduce) select(aka filter) และที่ขาดไม่ได้สารพัดอื่น ๆ แนะนำ (หากคุณต้องใช้ Matlab)
Ahmed Fasih

คำตอบ:


133

คำตอบสั้น ๆ : ฟังก์ชันในตัวarrayfunทำสิ่งที่mapฟังก์ชันของคุณทำกับอาร์เรย์ตัวเลข:

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

     1     4     9    16    25    36    49    64    81   100

มีฟังก์ชันในตัวอีกสองฟังก์ชันที่ทำงานในลักษณะเดียวกัน: cellfun(ซึ่งทำงานในองค์ประกอบของอาร์เรย์เซลล์) และstructfun(ซึ่งทำงานในแต่ละฟิลด์ของโครงสร้าง)

แต่ฟังก์ชั่นเหล่านี้มักจะไม่จำเป็นถ้าคุณใช้ประโยชน์จาก vectorization เฉพาะโดยใช้องค์ประกอบที่ชาญฉลาดดำเนินการทางคณิตศาสตร์ สำหรับตัวอย่างที่คุณให้โซลูชัน vectorized จะเป็น:

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

     1     4     9    16    25    36    49    64    81   100

การดำเนินการบางอย่างจะทำงานข้ามองค์ประกอบโดยอัตโนมัติ (เช่นการเพิ่มค่าสเกลาร์ให้กับเวกเตอร์) ในขณะที่ตัวดำเนินการอื่น ๆ มีไวยากรณ์พิเศษสำหรับการดำเนินการตามองค์ประกอบ (แสดงโดย.ตัวดำเนินการก่อนหน้า) ฟังก์ชันในตัวจำนวนมากใน MATLAB ได้รับการออกแบบมาเพื่อดำเนินการกับอาร์กิวเมนต์เวกเตอร์และเมทริกซ์โดยใช้การดำเนินการตามองค์ประกอบ (มักใช้กับมิติที่กำหนดเช่นsumและmeanเป็นต้น) ดังนั้นจึงไม่จำเป็นต้องใช้ฟังก์ชันแผนที่

สรุปได้ว่าวิธีต่างๆในการยกกำลังสององค์ประกอบในอาร์เรย์มีดังนี้

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)!
Diederick C.Niehorster

10

นอกเหนือจากการดำเนินการแบบเวกเตอร์และองค์ประกอบแล้วยังมีcellfunฟังก์ชันการแมปเหนืออาร์เรย์ของเซลล์อีกด้วย ตัวอย่างเช่น:

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

หาก 'UniformOutput' เป็นจริง (หรือไม่ได้ระบุไว้) ระบบจะพยายามเชื่อมต่อผลลัพธ์ตามขนาดของอาร์เรย์เซลล์ดังนั้น

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

2

วิธีแก้ปัญหาที่ค่อนข้างง่ายโดยใช้เวกเตอร์ของ 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) คือการอ้างอิงถึงเวกเตอร์ขนาด 5 ที่มีองค์ประกอบของ c ที่ดัชนีที่กำหนดโดย b ตอนนี้ถ้าคุณกำหนดค่าให้กับเวกเตอร์อ้างอิงนี้ค่าดั้งเดิมใน c จะถูกเขียนทับเนื่องจาก c (b) มีการอ้างอิงถึงค่าใน c และไม่มีสำเนา


1

ดูเหมือนว่า arrayfun ในตัวจะไม่ทำงานหากผลลัพธ์ที่ต้องการคืออาร์เรย์ของฟังก์ชันเช่น: map (@ (x) [xx ^ 2 x ^ 3], 1: 10)

mod เล็กน้อยด้านล่างทำให้การทำงานนี้ดีขึ้น:

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จะใช้ได้กับตัวอย่างของคุณคุณเพียงแค่ต้องรวมอาร์กิวเมนต์อินพุต..., 'UniformOutput', false);เพื่อสร้างเอาต์พุตอาร์เรย์เซลล์ที่มีอาร์เรย์ของคุณจากนั้นจัดรูปแบบและรวมเข้าด้วยกันตามที่คุณต้องการเป็นอาร์เรย์ที่ไม่ใช่เซลล์
gnovice

0

หาก matlab ไม่มีฟังก์ชันแผนที่ในตัวอาจเป็นเพราะการพิจารณาด้านประสิทธิภาพ ในการนำไปใช้งานของคุณคุณกำลังใช้การวนซ้ำเพื่อวนซ้ำองค์ประกอบของรายการซึ่งโดยทั่วไปมักจะขมวดอยู่ในโลกของ matlab ฟังก์ชัน matlab ในตัวส่วนใหญ่เป็น "vectorized" กล่าวคือมีประสิทธิภาพมากกว่าในการเรียกใช้ฟังก์ชันบนอาร์เรย์ทั้งหมดมากกว่าที่จะวนซ้ำด้วยตัวเองและเรียกใช้ฟังก์ชันสำหรับแต่ละองค์ประกอบ

กล่าวอีกนัยหนึ่งนี้


a = 1:10;
a.^2

เร็วกว่านี้มาก


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

สมมติว่าคุณนิยามแผนที่


2
ฉันคิดว่าประเด็นของเขาไม่ใช่ว่าเขาต้องการให้มันวนซ้ำ แต่เพียงแค่ระบุว่ามีอาร์เรย์ของผลลัพธ์ของการใช้ฟังก์ชันที่ให้มากับองค์ประกอบที่เกี่ยวข้องของอาร์เรย์ที่ให้มา ฉันไม่รู้จัก matlab มากนัก แต่ดูเหมือนว่า arrayfun จะทำงานได้ดี

1
ฟังก์ชันและตัวดำเนินการ Matlab ในตัวส่วนใหญ่ทำเช่นนั้นอยู่แล้ว: ทำงานกับแต่ละองค์ประกอบของอาร์เรย์อินพุตและส่งคืนอาร์เรย์ของผลลัพธ์ที่สอดคล้องกัน
Dima

0

คุณไม่ต้องการ mapmapตั้งแต่เกลาฟังก์ชั่นที่ใช้กับรายการของค่าถูกนำไปใช้กับแต่ละค่าและด้วยเหตุนี้ทำงานคล้ายกับ เพียงแค่พยายามที่

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

f(l)

ในกรณีของคุณคุณสามารถเขียน

l.^2

9
-1: ที่จริงไม่จริง Matlab ไม่มีระบบชนิดที่แข็งแกร่งพอที่จะระบุฟังก์ชันสเกลาร์ f ถูกเรียกด้วยเวกเตอร์และเพิ่มเวกเตอร์เดี่ยวในตัวอย่างของคุณ ในการตรวจสอบสิ่งนี้ให้กำหนดโปรไฟล์ตัวอย่างโค้ดของคุณ ("profile on" ก่อนที่จะรันโค้ดจากนั้นจึง "profile off report" ตามหลัง) คุณจะเห็นว่ามีสายเดียวถึง f
Mr Fooz

-1

การทำให้โซลูชันเป็นเวกเตอร์ตามที่อธิบายไว้ในคำตอบก่อนหน้านี้น่าจะเป็นทางออกที่ดีที่สุดสำหรับความเร็ว Vectorizing ยังเป็น Matlaby มากและรู้สึกดี

ด้วยเหตุนี้ Matlab จึงมีคลาสคอนเทนเนอร์แผนที่

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


Op กำลังพูดถึงฟังก์ชันลำดับที่สูงกว่าเช่นcellfunet al. ไม่ใช่ตารางแฮชหรือคู่คีย์ - ค่า
Ahmed Fasih
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.