Bir işlev tarafından döndürülen bir MATLAB dizisini önce yerel bir değişkene atamadan nasıl dizine ekleyebilirim?


363

Örneğin, orta değeri okumak istiyorsanız magic(5), bunu şöyle yapabilirsiniz:

M = magic(5);
value = M(3,3);

almak için value == 13. Bunlardan biri gibi bir şey yapmak istiyorum:

value = magic(5)(3,3);
value = (magic(5))(3,3);

ara değişkenten vazgeçmek. Ancak MATLAB Unbalanced or unexpected parenthesis or bracket, önceki parantezden şikayetçi 3.

Bir diziden / matristen değerleri önce bir değişkene atamadan okumak mümkün müdür?


2
Bu konuyla ilgili aşağıdaki makaleyi de buldum: mathworks.com/matlabcentral/newsreader/view_thread/280225 Herkes bu tema hakkında yeni bilgiye sahip, uygulanacak mı?

2
Bu sözdizimi aslında Octave'de iyi çalışıyor. Bu sorunu sadece MATLAB kullanan meslektaşlarımın kodumu çalıştırmayla ilgili sorunları olduğunda keşfettim.
sffc

2
Özetle MATLAB.
user76284

1
Özyinelemeli çıkarma da Sürüm 6'dan beri Scilab'da ( scilab.org ) çalışır .
Stéphane Mottelet

testmatrix('magi', 5)(3, 3)Scilab ve magic(5)(3, 3)bir cazibe gibi hem iş hem de Octave üzerinde!
Foad

Yanıtlar:


384

Aslında olduğunu ne istediğinizi yapmak mümkün, ancak indeksleme operatörünün fonksiyonel formunu kullanmak zorunda. Düğmesini kullanarak bir dizin oluşturma işlemi gerçekleştirdiğinizde (), aslında subsrefişleve bir çağrı yaparsınız . Yani, olsa bile olamaz bunu:

value = magic(5)(3, 3);

Bunu yapabilirsiniz :

value = subsref(magic(5), struct('type', '()', 'subs', {{3, 3}}));

Çirkin ama mümkün. ;)

Genel olarak, indeksleme adımını bir işlev çağrısı olarak değiştirmeniz yeterlidir, böylece birbirini takip eden iki parantez kümeniz olmaz. Bunu yapmanın başka bir yolu , aboneli indekslemeyi yapmak için kendi anonim işlevinizi tanımlamak olacaktır . Örneğin:

subindex = @(A, r, c) A(r, c);     % An anonymous function for 2-D indexing
value = subindex(magic(5), 3, 3);  % Use the function to index the matrix

Ancak, her şey söylendiğinde ve yapıldığında geçici yerel değişken çözümü çok daha okunabilir ve kesinlikle önereceğim şey.


26
ne biliyorsun! rağmen oldukça çirkin ve muhtemelen bir temp-var çözüm daha az okunabilir katılıyorum. Etkileyici matlab bilgisi için +1!
ikinci

57
Bu iğrenç, ama çok açık bir cevap. İyi iş! Buna geri dönüş yolu olacağını tahmin etmeliydim. Temp değişkeniyle devam edeceğimi düşünüyorum.
Joe Kearney

29
Ancak ara değişkenin hala tamamen yaratıldığını unutmayın. Dolayısıyla amaç, geçici bir yerel değişken oluşturmak zorunda kalmadan bellek tasarrufu yapmaksa, şans yok.
Sam Roberts

8
@ SamRoberts: Bunu Matlab gibi katı bir dille gerçekten çözemezsiniz. İnsanların bunu istemesinin ana nedeni, bellek tasarrufu değil, özlü / okunabilirliktir.
Mekanik salyangoz

5
@SamRoberts: true, ancak does çağıran yükünden kurtarmayacaksa clear(hiç kimse yapar) geçici üzerine - Geçici etrafında uzun sopa eğilimi
Rody Oldenhuis

131

Sadece vardı iyi blog yazısı üzerine Matlab'in Sanatı Loren kudreti yardımı olduğunu birkaç taşlarla bir kaç gün önce. Özellikle, aşağıdaki gibi yardımcı işlevleri kullanarak:

paren = @(x, varargin) x(varargin{:});
curly = @(x, varargin) x{varargin{:}};

nerede paren()kullanılabilir

paren(magic(5), 3, 3);

dönecekti

ans = 16

Ayrıca bu gnovice cevap daha hızlı olacağını, ancak kontrol ettim (Profiler kullanın !!!). Bununla birlikte, bu işlev tanımlarını bir yere dahil etmeniz gerekir. Şahsen onları benim yolumda bağımsız işlevler haline getirdim, çünkü süper kullanışlılar.

Bu işlevler ve diğerleri artık MATLAB Eklenti Gezgini'nde veya Dosya Değişimi'nde kullanılabilen İşlevsel Programlama Yapıları eklentisinde kullanılabilir .


2
Bu, gnovice'nin cevabının ikinci yarısının biraz daha genel bir versiyonudur; aynı zamanda iyi.
Joe Kearney

Ne olmuş myfunc().attr?
gerrit

@gerrit, nasıl yardım eder? ve veritabanı araç kutusuna sahip olmadığınız sürece x.attr () alanı kullanılamaz.
T.Furfaro

@ T.Furfaro Huh? Eğer myfunc()getiriler bir öznitelik içeren bir yapı attrerişmeye sonra, attrşu anda yapmam gereken S = myfunc(); S.attr. Soru, ve yardımcılarına getattr(myfunc(), 'attr')benzer bir yardımcı fonksiyona sahip olup olamayacağımızdır . Bunun veritabanı araç kutusu ile ne ilgisi olduğunu anlamıyorum. parencurly
gerrit

2
@gerrit Üzgünüm, toplam karışıklık ("attr" un keyfi olduğunu bilmiyordum - db tb'de böyle bir alan açıklığı tanımlanmış). Sana olan aradığınızı inanmak () GetField
T. Furfaro

75

Belgelenmemiş özellikleri kullanma hakkında ne düşünüyorsunuz:

>> builtin('_paren', magic(5), 3, 3)               %# M(3,3)
ans =
    13

veya hücre dizileri için:

>> builtin('_brace', num2cell(magic(5)), 3, 3)     %# C{3,3}
ans =
    13

Tıpkı sihir gibi :)


GÜNCELLEME:

Kötü haber, yukarıdaki kesmek artık R2015b'de çalışmıyor ! Bu iyi, belgesiz işlevsellikti ve desteklenen bir özellik olarak ona güvenemeyiz :)

Bu tür şeyleri nerede bulacağınızı merak edenler için klasöre bakın fullfile(matlabroot,'bin','registry'). Orada her türlü güzellikleri listeleyen bir sürü XML dosyası var. Bu işlevlerden bazılarını doğrudan çağırmanın MATLAB oturumunuzu kolayca çökertebileceği konusunda uyarınız.


@RodyOldenhuis: Şimdi hatırlamıyorum, bazı gömülü kodlarda okumalıyım sanırım;)
Amro

2
':'Hatayı önlemek için iki nokta üst üste (:) operatörü kesme işaretleriyle birlikte kullanılmalıdır Undefined function or variable "builtin".
Dominik

@Dominik: Tamam, sen 2 sütun kesmek isteyecektir demek ki şöyle olacaktır: builtin('_paren', magic(5), ':', 2)(bazı yerlerde o kadar doğrudan alıntılar olmadan çalışır :aksine ':'bir işlev içinde doğrudan değil istemi komutu çalışırken gibi, sanırım. ayrıştırıcıda bir hata!)
Amro

2
Sanırım bununla kullanmanın bir yolu yok endmu?
knedlsepp

2
@knedlsepp: Hayır, ne yazık ki bütün end-drickery bu sözdiziminde çalışmıyor, dizinlemenizde açık olmanız gerekecek .. (Listelenen diğer cevapların çoğu için aynı sınırlama geçerlidir)
Amro

54

En azından MATLAB 2013a'da aşağıdaki getfieldgibi kullanabilirsiniz :

a=rand(5);
getfield(a,{1,2}) % etc

(1,2) 'deki öğeyi almak için


5
Bu aslında güzel bir yöntem. Herhangi bir dezavantajı var mı?
mmumboss

6
@mmumboss: Bu belgesiz davranış, bu işlevsellik gelecekteki sürümlerde önceden haber verilmeksizin kaybolabilir. Bunun dışında hiçbir dezavantajı yoktur.
Daniel

6
MATLAB2017b'den itibaren, bu işlev belgelenmiştir.
njspeer

15

maalesef gibi sözdizimi magic(5)(3,3)matlab tarafından desteklenmemektedir. geçici ara değişkenler kullanmanız gerekir. kullandıktan sonra belleği boşaltabilirsiniz, örn.

tmp = magic(3);
myVar = tmp(3,3);
clear tmp

12

Çalışma sürelerini standart yolla karşılaştırırsanız (sonucu atar ve girişlere erişir), bunların tamamen aynı olduğunu unutmayın.

subs=@(M,i,j) M(i,j);
>> for nit=1:10;tic;subs(magic(100),1:10,1:10);tlap(nit)=toc;end;mean(tlap)

ans =

0.0103

>> for nit=1:10,tic;M=magic(100); M(1:10,1:10);tlap(nit)=toc;end;mean(tlap)

ans =

0.0101

Bana göre, sonuçta: MATLAB'ın işaretçileri yok, onunla yaşamak zorundasınız.


6

Yeni bir işlev yaparsanız daha kolay olabilir:

function [ element ] = getElem( matrix, index1, index2 )
    element = matrix(index1, index2);
end

ve sonra kullanın:

value = getElem(magic(5), 3, 3);

1
ama bu tam olarak subrefbunu yapar ... ama daha genel bir şekilde.
Shai

2
evet, daha genel bir yol, ama dost değil ... bence çok çirkin.
Vugar

4

İlk gösteriminiz bunu yapmanın en kısa yoludur:

M = magic(5);  %create
value = M(3,3);  % extract useful data
clear M;  %free memory

Bunu bir döngüde yapıyorsanız, her seferinde M'yi yeniden atayabilir ve açık ifadeyi de göz ardı edebilirsiniz.


6
Bunun daha özlü olduğunu ve söylediğiniz gibi, bir döngüde temizliğin iyi bir fikir olduğunu kabul ediyorum, ancak soru özellikle ara atamanın önlenip önlenemeyeceği idi.
Joe Kearney

1

Amro'nun cevabını tamamlamak için fevalbunun yerine kullanabilirsiniz builtin. Operatör işlevini aşırı yüklemeye çalışmadığınız sürece, hiçbir fark yoktur:

BUILTIN (...), FEVAL (...) ile aynıdır, ancak aşırı yüklenmiş bir tane olsa bile işlevin orijinal yerleşik sürümünü çağırması dışında (bunun çalışması için BUILTIN'i aşırı yüklememeniz gerekir).

>> feval('_paren', magic(5), 3, 3)               % M(3,3)
ans =
    13

>> feval('_brace', num2cell(magic(5)), 3, 3)     % C{3,3}
ans =
    13

İlginç olan şey , fonksiyonun aşırı yüklenip yüklenmediğini kontrol etmesi gereken garip olduğu için en azından Matlab 2013b'de (~% 3.5 kadar) fevalbiraz daha hızlı olduğu builtingörülüyor :fevalbuiltin

>> tic; for i=1:1e6, feval('_paren', magic(5), 3, 3); end; toc;
Elapsed time is 49.904117 seconds.
>> tic; for i=1:1e6, builtin('_paren', magic(5), 3, 3); end; toc;
Elapsed time is 51.485339 seconds.

Aslında garip değil: MATLAB tanımlı fonksiyonların bir listesini tutar, yapacak fazla arama yoktur. feval"normal" bir şey yapar ve bu nedenle bu listeyi tam olarak kullanabilir. builtinyalnızca yerleşik işlevleri bulabilmesi için başka bir yerde arama yapmalıdır. Muhtemelen bu durum neredeyse “normal” vaka kadar optimize edilmemiştir, çünkü neden çok sık kullanılmayan bir şeyi optimize etmek için para koydunuz?
Cris Luengo
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.