먼저 로컬 변수에 할당하지 않고 함수에서 반환 한 MATLAB 배열을 어떻게 인덱싱 할 수 있습니까?


363

예를 들어에서의 중간 값을 읽으려면 다음 magic(5)과 같이하십시오.

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

얻을 value == 13. 다음 중 하나와 같은 작업을 수행하고 싶습니다.

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

중간 변수를 제거합니다. 그러나 MATLAB은 Unbalanced or unexpected parenthesis or bracket앞에있는 첫 번째 괄호에 대해 불평 합니다 3.

변수 / 변수를 먼저 변수에 할당하지 않고 배열 / 매트릭스에서 값을 읽을 수 있습니까?


2
또한이 주제에 대해 다음 기사를 찾았습니다. mathworks.com/matlabcentral/newsreader/view_thread/280225 이 주제에 대한 새로운 정보가있는 사람이 있습니까?

2
이 구문은 실제로 Octave에서 제대로 작동합니다. MATLAB을 사용하는 동료가 내 코드를 실행하는 데 문제가있을 때만이 문제를 발견했습니다.
sffc

2
간단히 말해서 MATLAB.
user76284

1
재귀 추출은 버전 6 이후 Scilab ( scilab.org ) 에서도 작동합니다 .
Stéphane Mottelet

testmatrix('magi', 5)(3, 3)Scilab에와 magic(5)(3, 3)마법처럼 모두 작업 옥타브에!
Foad

답변:


384

실제로 원하는 것을 수행하는 것이 가능하지만 기능적인 형태의 인덱싱 연산자를 사용해야합니다. 를 사용하여 인덱싱 작업을 수행하면 ()실제로 subsref함수를 호출하게 됩니다. 따라서이 작업을 수행 할 수는 없지만 :

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

당신 이것을 있습니다 :

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

추악하지만 가능합니다. ;)

일반적으로 인덱싱 단계를 함수 호출로 변경하면 바로 다음에 두 세트의 괄호가 없어집니다. 이를 수행하는 또 다른 방법 은 첨자 인덱싱을 수행하기 위해 자신의 익명 함수 를 정의하는 것 입니다. 예를 들면 다음과 같습니다.

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

그러나 모든 것이 말되고 완료되면 임시 로컬 변수 솔루션을 훨씬 더 읽기 쉽고 확실히 제안 할 것입니다.


26
잘 아세요! 비록 그것이 추악하고, 아마도 임시 Var 솔루션보다 읽기 쉽지 않다는 데 동의합니다. 눈에 잘 띄지 않는 MATLAB 지식 +1!
두 번째

57
그것은 역겨운 일이지만 매우 명확한 대답입니다. 잘 했어! 그것에 대한 뒷길이있을 것이라고 추측했을 것입니다. temp 변수를 계속 사용할 것입니다.
Joe Kearney

29
그래도 중간 변수는 여전히 완전히 생성됩니다. 따라서 임시 로컬 변수를 만들지 않고 메모리를 절약하는 것이 목적이라면 운이 없습니다.
샘 로버츠

8
@ SamRoberts : Matlab과 같은 엄격한 평가 언어로 그 문제를 해결할 수는 없습니다. 사람들이 이것을 원하는 주된 이유는 메모리 절약이 아니라 간결함 / 가독성입니다.
기계 달팽이

5
@SamRoberts : 사실,하지만은 않습니다 호출의 부담에서 당신 저장 clear(아무도 이제까지하지 않습니다하는) 임시에이 - 임시 주위에 더 이상 집착하는 경향이있다
RODY Oldenhuis

131

며칠 전에 Loren의 Matlab에 관한 좋은 블로그 게시물 이 있었는데 도움이 될만한 몇 가지 보석이 있습니다. 특히 다음과 같은 도우미 기능 사용

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

어디에서 paren()사용할 수 있습니까

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

돌아올 것이다

ans = 16

나는 이것이 gnovice의 대답보다 빠를 것이라고 생각하지만 확인하지 않았습니다 (프로필러 사용 !!!). 즉,이 함수 정의를 어딘가에 포함시켜야합니다. 나는 개인적으로 내 경로에서 독립적 인 기능을 만들었습니다. 매우 유용하기 때문입니다.

이러한 함수 및 기타 함수는 이제 MATLAB 애드온 탐색기 또는 파일 교환을 통해 제공되는 Functional Programming Constructs 애드온에서 사용할 수 있습니다 .


2
이것은 gnovice의 답변 후반부의 약간 더 일반적인 버전입니다. 또한 좋습니다.
Joe Kearney

무엇에 대해 myfunc().attr?
gerrit

@gerrit, 어떻게 도와 줍니까? 데이터베이스 도구 상자가 없으면 x.attr () 필드를 사용할 수 없습니다.
T. Furfaro

@ T.Furfaro Huh? myfunc()속성이 포함 된 구조를 반환하는 경우 현재 attr액세스 attr하려면해야 S = myfunc(); S.attr합니다. 문제는 헬퍼 와 헬퍼 getattr(myfunc(), 'attr')와 같은 헬퍼 기능을 가질 수 있는지 입니다. 데이터베이스 도구 상자와 관련이 무엇인지 이해하지 못합니다. parencurly
gerrit

2
@gerrit 죄송합니다, 총 혼란입니다 (귀하의 "attr"이 임의적이라는 것을 알지 못했습니다-db tb에는 명시 적으로 정의 된 필드가 있습니다). 나는 당신이 찾고있는 것이 getfield ()
T. Furfaro

75

문서화되지 않은 기능 사용에 대해 어떻게 생각하십니까?

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

또는 셀형 배열의 경우 :

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

마술처럼 :)


최신 정보:

나쁜 소식, 위의 핵은 더 이상 R2015b 에서 작동하지 않습니다 ! 괜찮습니다. 문서화되지 않은 기능이므로 지원되는 기능으로 사용할 수 없습니다. :)

이 유형의 것을 어디에서 찾을 수 있는지 궁금한 분은 폴더를 찾으십시오 fullfile(matlabroot,'bin','registry'). 모든 종류의 장점을 나열하는 XML 파일이 많이 있습니다. 이러한 함수 중 일부를 직접 호출하면 MATLAB 세션이 쉽게 중단 될 수 있습니다.


@RodyOldenhuis : 지금 기억 나지 않습니다. 매장 된 코드로 읽었어야한다고 생각합니다.)
Amro

2
':'오류를 피 하려면 콜론 (:) 연산자를 아포스트로피와 함께 사용해야합니다 Undefined function or variable "builtin".
도미니크

@Dominik : 맞습니다. 두 번째 열을 슬라이스하고 싶다고 말하십시오. builtin('_paren', magic(5), ':', 2)(특정 위치 에서는 명령 프롬프트에서 함수 내부가 아닌 직접 명령 프롬프트에서 실행할 때 와 :는 달리 따옴표없이 직접 ':'작동합니다. 그것은 파서의 버그입니다!)
Amro

2
나는 end이것과 함께 사용할 수 있는 방법이 있다고 생각하지 않습니까?
knedlsepp 2019

2
@knedlsepp : 아니, 불행하게도 전체 end-trickery는 이 구문에하지 작업, 당신은 당신의 색인에 명시해야합니다 않습니다 .. (동일 제한은 대부분의 다른 목록에 대한 답변 적용)
암로

54

적어도 MATLAB 2013a에서는 다음 getfield과 같이 사용할 수 있습니다 .

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

(1,2)에서 요소를 얻으려면


5
이것은 실제로 좋은 방법입니다. 어떤 단점이 있습니까?
mmumboss

6
@mmumboss : 그것은 문서화되지 않은 행동이며,이 기능은 차후 버전에서 예고없이 사라질 수 있습니다. 이 외에도 단점이 없습니다.
Daniel

6
MATLAB2017b부터이 기능이 문서화되었습니다.
njspeer

15

불행히도 같은 구문 magic(5)(3,3)은 matlab에서 지원되지 않습니다. 임시 중간 변수를 사용해야합니다. 사용 후 메모리를 비울 수 있습니다. 예 :

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

12

실행 시간을 표준 방식과 비교하면 (결과에 할당 한 다음 항목에 액세스) 정확히 동일합니다.

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

내 의견으로는, 결론은 : MATLAB에는 포인터가 없으므로 함께 사용해야합니다.


6

새로운 기능을 만들면 더 간단 할 수 있습니다.

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

그리고 그것을 사용하십시오 :

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

1
그러나 이것은 정확히 무엇 subref을하는 것이지만보다 일반적인 방식입니다.
Shai

2
예, 좀 더 일반적인 방법이지만 친절하지는 않습니다.
Vugar

4

초기 표기법은 가장 간결한 방법입니다.

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

루프 에서이 작업을 수행하는 경우 매번 M을 다시 할당하고 명확한 명령문도 무시할 수 있습니다.


6
나는 이것이 더 간결하다는 데 동의하고, 말한 것처럼 지우기는 루프에서 좋은 생각이지만, 중간 과제를 피할 수 있는지에 대한 질문이 있습니다.
Joe Kearney

1

Amro의 답변을 보완하기 위해 feval대신 사용할 수 있습니다 builtin. 연산자 함수를 오버로드하지 않으면 실제로 차이가 없습니다.

BUILTIN (...)은 FEVAL (...)과 동일하지만 오버로드 된 기능이 존재하더라도 함수의 원래 내장 버전을 호출한다는 점을 제외하면 (BUILTIN에 과부하가 걸리지 않아야 함)

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

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

흥미로운 것은 즉 feval단지 작은 조금 더 빨리 이상의 것 같다 builtin(~ 3.5 %로), 주어진 이상한 matlab에 2013b, 적어도 feval함수가 오버로드 된 경우 요구 사항이 달리 확인 builtin:

>> 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.

실제로는 이상하지 않습니다. MATLAB은 정의 된 함수 목록을 유지하므로 검색 할 것이 많지 않습니다. feval"정상적인"작업을 수행하므로이 목록을 최대한 활용할 수 있습니다. builtin내장 함수 만 찾을 수 있도록 다른 곳을 검색해야합니다. 아마도이 사례는“정상적인”사례만큼 최적화되지 않았을 것입니다. 왜 자주 사용하지 않는 것을 최적화하기 위해 돈을 투자하겠습니까?
Cris Luengo 2016 년
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.