수색…


셀과 배열에서 작동하는 유용한 함수

이 간단한 예제는 MATLAB : cellfun , arrayfun 사용하기 시작한 이래로 매우 유용한 일부 함수에 대한 설명을 제공합니다. 아이디어는 배열 또는 셀 클래스 변수를 가져 와서 모든 요소를 ​​반복하고 각 요소에 전용 함수를 적용하는 것입니다. 적용 함수는 익명이거나 대개는 * .m 파일에 정의 된 일반 함수 일 수 있습니다.

간단한 문제부터 시작하여 폴더가 주어진 * .mat 파일 목록을 찾아야한다고 가정 해 보겠습니다. 이 예제에서는 먼저 현재 폴더에 * .mat 파일을 몇 개 만듭니다.

for n=1:10; save(sprintf('mymatfile%d.mat',n)); end

코드를 실행 한 후에 확장자가 * .mat 인 10 개의 새로운 파일이 있어야합니다. 다음과 같이 모든 * .mat 파일을 나열하는 명령을 실행하면 :

mydir = dir('*.mat');

우리는 dir 구조체의 배열을 얻어야한다. MATLAB은 이와 비슷한 출력을 제공해야합니다 :

10x1 struct array with fields:
    name
    date
    bytes
    isdir
    datenum

보시다시피이 배열의 각 요소는 몇 개의 필드가있는 구조입니다. 모든 정보는 실제로 각 파일에 관해서는 중요하지만 99 %에서는 파일 이름에만 관심이 있습니다. 구조체 배열에서 정보를 추출하기 위해 정확한 크기의 임시 변수를 만드는 루프, 각 요소의 이름을 추출한 다음 생성 된 변수에 저장하는 로컬 함수를 작성했습니다. 똑같은 결과를 얻는 훨씬 쉬운 방법은 앞서 언급 한 함수 중 하나를 사용하는 것입니다.

mydirlist = arrayfun(@(x) x.name, dir('*.mat'), 'UniformOutput', false)
mydirlist = 
    'mymatfile1.mat'
    'mymatfile10.mat'
    'mymatfile2.mat'
    'mymatfile3.mat'
    'mymatfile4.mat'
    'mymatfile5.mat'
    'mymatfile6.mat'
    'mymatfile7.mat'
    'mymatfile8.mat'
    'mymatfile9.mat'

이 기능은 어떻게 작동합니까? 일반적으로 두 개의 매개 변수를 사용합니다. 함수 핸들을 첫 번째 매개 변수로 사용하고 배열을 사용합니다. 그런 다음 함수는 주어진 배열의 각 요소에 대해 연산을 수행합니다. 세 번째와 네 번째 매개 변수는 선택 사항이지만 중요합니다. 출력이 규칙적인 것이 아니라는 것을 안다면 셀에 저장해야합니다. 이것은 UniformOutput false 를 설정해야한다는 것을 지적해야합니다. 기본적으로이 함수는 숫자의 벡터와 같은 정규 출력을 반환하려고 시도합니다. 예를 들어, 각 파일이 차지하는 디스크 공간의 크기에 대한 정보를 바이트 단위로 추출해 보겠습니다.

mydirbytes = arrayfun(@(x) x.bytes, dir('*.mat'))
mydirbytes =
       34560
       34560
       34560
       34560
       34560
       34560
       34560
       34560
       34560
       34560

또는 킬로바이트 :

mydirbytes = arrayfun(@(x) x.bytes/1024, dir('*.mat'))
mydirbytes =
   33.7500
   33.7500
   33.7500
   33.7500
   33.7500
   33.7500
   33.7500
   33.7500
   33.7500
   33.7500

이번에는 double의 정규 벡터가 출력됩니다. UniformOutput 은 기본적으로 true 로 설정되었습니다.

cellfun 은 비슷한 기능입니다. 이 함수와 arrayfuncellfun 이 셀 클래스 변수에서 작동한다는 cellfun . 'mydirlist'셀에 파일 이름 목록이있는 이름 만 추출하려면 다음과 같이이 함수를 실행하면됩니다.

mydirnames = cellfun(@(x) x(1:end-4), mydirlist, 'UniformOutput', false)
mydirnames = 
    'mymatfile1'
    'mymatfile10'
    'mymatfile2'
    'mymatfile3'
    'mymatfile4'
    'mymatfile5'
    'mymatfile6'
    'mymatfile7'
    'mymatfile8'
    'mymatfile9'

다시 말하지만, 출력은 숫자의 정규 벡터가 아니므로 출력을 셀 변수에 저장해야합니다.

아래의 예에서는 하나의 함수를 두 개 결합하여 확장명이없는 파일 이름 목록 만 반환합니다.

cellfun(@(x) x(1:end-4), arrayfun(@(x) x.name, dir('*.mat'), 'UniformOutput', false), 'UniformOutput', false)
ans = 
    'mymatfile1'
    'mymatfile10'
    'mymatfile2'
    'mymatfile3'
    'mymatfile4'
    'mymatfile5'
    'mymatfile6'
    'mymatfile7'
    'mymatfile8'
    'mymatfile9'

arrayfuncellfun 예상 입력 인 셀을 반환하기 때문에 매우 어렵 arrayfun . 이것에 대한 부수적 인 언급은 UniformOutput 을 명시 적으로 false로 설정하여 셀 변수에 결과를 반환하도록 강제 할 수 있다는 것입니다. 우리는 언제나 세포에서 결과를 얻을 수 있습니다. 정규 벡터로 결과를 얻지 못할 수도 있습니다.

필드에는 구조체 인 structfun 을 작동시키는 또 하나의 유사한 함수가 있습니다. 나는 특히 다른 두 사람만큼이나 유용하다고 생각하지는 않았지만 어떤 상황에서는 빛날 것입니다. 예를 들어 어떤 필드가 숫자인지 아닌지 알고 싶다면 다음 코드를 사용하여 답을 얻을 수 있습니다.

structfun(@(x) ischar(x), mydir(1))

dir 구조의 첫 번째와 두 번째 필드는 char 유형입니다. 따라서 출력은 다음과 같습니다.

 1
 1
 0
 0
 0

또한 출력은 true / false 의 논리 벡터입니다. 따라서 규칙적이고 벡터로 저장할 수 있습니다. 셀 클래스를 사용할 필요가 없습니다.

코드 접기 기본 설정

필요에 맞게 코드 접기 기본 설정을 변경할 수 있습니다. 따라서 코드 폴딩은 특정 구문 (예 : if block , for loop , Sections ...)에 대해 활성화 / 비활성화로 설정할 수 있습니다.

접는 기본 설정을 변경하려면 환경 설정 -> 코드 접기 :

여기에 이미지 설명을 입력하십시오.

그런 다음 코드의 어떤 부분을 접을 수 있는지 선택할 수 있습니다.

몇가지 정보:

  • 파일 내의 모든 위치에 커서를두고 마우스 오른쪽 버튼을 클릭 한 다음 상황 별 메뉴에서 코드 접기> 모두 확장 또는 코드 접기> 접기를 선택하여 파일의 모든 코드를 확장하거나 축소 할 수도 있습니다.
  • 축소 / 축소 된 코드의 일부는 Matlab 또는 m- 파일이 닫히고 다시 열린 후 상태를 유지한다는 의미에서 접기가 지속됩니다.

예 : 섹션에 대해 접기를 활성화하려면 :

흥미로운 옵션은 섹션을 접을 수있게하는 것입니다. 섹션은 두 개의 퍼센트 기호 ( %% )로 구분됩니다.

예 : '섹션'확인란을 선택하려면 다음을 수행하십시오.

여기에 이미지 설명을 입력하십시오.

다음과 유사한 긴 소스 코드를 보는 대신

여기에 이미지 설명을 입력하십시오.

섹션을 폴드하여 코드에 대한 일반적인 개요를 볼 수 있습니다. 여기에 이미지 설명을 입력하십시오.

그림 데이터 추출

몇 번, 나는 구원받은 재미있는 인물이 있었지만 데이터에 액세스하지 못했습니다. 이 예제는 그림에서 정보를 추출하는 방법을 보여줍니다.

주요 기능은 findobjget 입니다. findobj 는 객체의 속성이나 속성 ( Type 이나 Color 등)이 지정된 객체에 대한 핸들러를 반환합니다. 일단 라인 객체가 발견되면 get 은 속성에서 보유하는 모든 값을 반환 할 있습니다. Line 객체는 XData , YDataZData 속성의 모든 데이터를 유지합니다. 그림에 3D 플롯이 포함되어 있지 않으면 마지막 것은 보통 0입니다.

다음 코드는 sin 함수와 임계 값 및 범례의 두 줄을 보여주는 그림 예제를 만듭니다.

t = (0:1/10:1-1/10)';
y = sin(2*pi*t);
plot(t,y);
hold on;
plot([0 0.9],[0 0], 'k-');
hold off;
legend({'sin' 'threshold'});

findobj를 처음 사용하면 두 행에 두 개의 핸들러가 반환됩니다.

findobj(gcf, 'Type', 'Line')
ans = 
  2x1 Line array:

  Line    (threshold)
  Line    (sin)

결과 범위를 좁히기 위해 findobj 는 논리 연산자 -and -or 및 속성 이름의 조합을 사용할 수도 있습니다. 예를 들어 DiplayNamesin 인 라인 객체를 DiplayName XDataYData 읽을 수 있습니다.

lineh = findobj(gcf, 'Type', 'Line', '-and', 'DisplayName', 'sin');
xdata = get(lineh, 'XData');
ydata = get(lineh, 'YData');

데이터가 동일한 지 확인하십시오.

isequal(t(:),xdata(:))
ans =
     1
isequal(y(:),ydata(:))
ans =
     1

마찬가지로 검은 선 (임계 값)을 제외하여 결과를 좁힐 수 있습니다.

lineh = findobj(gcf, 'Type', 'Line', '-not', 'Color', 'k');
xdata = get(lineh, 'XData');
ydata = get(lineh, 'YData');

마지막 확인은이 그림에서 추출한 데이터가 동일 함을 확인합니다.

isequal(t(:),xdata(:))
ans =
     1
isequal(y(:),ydata(:))
ans =
     1

익명 함수를 사용한 함수형 프로그래밍

익명 함수는 함수형 프로그래밍에 사용될 수 있습니다. 해결해야 할 주된 문제는 재귀를 고정하는 기본 방법이 없지만 한 줄로 구현할 수 있다는 것입니다.

if_ = @(bool, tf) tf{2-bool}();

이 함수는 부울 값과 두 함수의 셀 배열을 허용합니다. 이 함수 중 첫 번째는 부울 값이 true로 평가되면 평가되고 두 ​​번째 것은 부울 값이 false로 평가되면 평가됩니다. 우리는 계승 함수를 지금 쉽게 작성할 수 있습니다 :

fac = @(n,f) if_(n>1, {@()n*f(n-1,f), @()1});

여기에서 문제는 재귀 호출을 직접 호출 할 수 없다는 것입니다. 함수가 아직 변수에 할당되지 않았으므로 오른쪽이 평가 될 때입니다. 그러나 우리는이 단계를 글쓰기로 끝낼 수 있습니다.

factorial_ = @(n)fac(n,fac);

이제 @(n)fac(n,fac) 은 계승 함수를 재귀 적으로 evaulates. 쉽게 구현할 수있는 y- 결합자를 사용하여 함수 프로그래밍에서이를 수행하는 또 다른 방법은 다음과 같습니다.

y_ = @(f)@(n)f(n,f);

이 도구를 사용하면 계승 함수가 더 짧아집니다.

factorial_ = y_(fac);

또는 직접 :

factorial_ = y_(@(n,f) if_(n>1, {@()n*f(n-1,f), @()1}));

여러 개의 그림을 동일한 .fig 파일에 저장

그래픽 배열에 여러 그림 핸들을 배치하면 여러 그림을 동일한 .fig 파일에 저장할 수 있습니다

h(1) = figure;
scatter(rand(1,100),rand(1,100));

h(2) = figure;
scatter(rand(1,100),rand(1,100));

h(3) = figure;
scatter(rand(1,100),rand(1,100));

savefig(h,'ThreeRandomScatterplots.fig');
close(h);

이것은 그래픽 배열 h의 각 부분 인 무작위 데이터의 3 개의 산점도를 만듭니다. 그런 다음 그래픽 배열은 일반 그림과 같이 savefig를 사용하여 저장할 수 있지만 추가 인수로 그래픽 배열의 핸들을 사용합니다.

흥미로운 측면은 숫자를 열 때 저장된 것과 동일한 방식으로 정렬 된 상태로 유지되는 경향이 있다는 것입니다.

댓글 블록

코드의 일부를 주석 처리하려면 주석 블록이 유용 할 수 있습니다. 코멘트 블록은 새 줄에서 %{ 로 시작하고 %} 로 끝납니다.

a = 10;
b = 3;
%{
c = a*b;
d = a-b;
%}

이렇게하면 코드를 더 깨끗하고 컴팩트하게 만들기 위해 주석 처리 한 섹션을 접을 수 있습니다.

이 블록은 코드의 일부를 토글 링하는 데 유용합니다. 블록의 주석 처리를 제거하기 위해서해야 할 일은 strats 전에 다른 % 를 추가하는 것입니다.

a = 10;
b = 3;
%%{ <-- another % over here
c = a*b;
d = a-b;
%}

때로는 코드의 일부분을 주석 처리하지만 들여 쓰기에 영향을 미치지 않고 원하는 경우가 있습니다.

for k = 1:a
    b = b*k;
    c = c-b;
    d = d*c;
    disp(b)
end

일반적으로 코드 블록을 표시하고 Ctrl + r을 눌러 주석 처리합니다 ( % 를 모든 행에 자동으로 추가 한 다음 나중 들여 쓰기로 Ctrl + i를 누르면 코드 블록이 올바른 계층 구조로 이동합니다) 장소를 차지하고 오른쪽으로 너무 많이 이동했습니다.

for k = 1:a
    b = b*k;
    %     c = c-b;
    %     d = d*c;
    disp(b)
end

이 문제를 해결하는 방법은 주석 블록을 사용하는 것이므로 블록의 내부 부분이 정확하게 들여 쓰기됩니다.

for k = 1:a
    b = b*k;
    %{
    c = c-b;
    d = d*c;
    %}
    disp(b)
end


Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow