Excel

Lambda 함수 매개변수 2개 이상인 경우(1)

별동산 2023. 1. 18. 08:04
반응형

=LAMBDA([parameter1, parameter2, ...,] 계산식)
Lambda함수의 구문이 Parameter를 여러 개 전달하고, 이를 이용해 계산식에 적용한 후 결괏값을 반환하므로 2개 이상의 매개변수를 전달할 수 있습니다.

Lambda함수는 Microsoft 365용 Excel, Microsoft 365용 Excel(Mac용), 웹용 Excel에서만 이용가능합니다. 따라서 이전 버전이란 함수 목록에 표시되지 않고, Lambda함수로 된 수식은 #NAME! 에러가 발생합니다.

Lambda함수(여러 개 매개변수).xlsx
0.01MB



1. 직각삼각형의 빗변의 길이 구하기

가. 수식을 이용한 경우

피타고라스의 정리에 따라 밑변과 높이의 제곱을 더한 후 제곱근을 구하면 됩니다.

제곱근을 구하는 함수는 SqRt(Square Root)이고,
제곱을 구하는 함수는 Power인데, ^(Shift+6 키를 눌러 입력)를 사용하는 것이 편리합니다.
따라서, 수식은 =sqrt(sum(밑변^2,높이^2)) 이고,

이를 Lambda함수에 대입하면
=lambda(밑변, 높이, sqrt(sum(밑변^2,높이^2))가 되고,
뒷부분에 밑변과 높이의 값을 괄호 안에 넣어서 전달하면 됩니다.

밑변과 높이가 A2와 B2셀에 있을 경우 Lambda 수식은
=LAMBDA(밑변,높이,SQRT(SUM(밑변^2,높이^2)))(A2, B2)
가 됩니다.

Lambda 함수를 사용한 수식

 

나. 이름 관리자(사용자 정의 함수)를 이용한 경우

아래 글에서 Lambda함수 식을 이름에 할당하는 방법을 참고 바랍니다.
https://lsw3210.tistory.com/entry/%EC%88%98%EC%8B%9D%EC%9D%84-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0-%EC%89%BD%EA%B2%8C-%EB%A7%8C%EB%93%A4%EA%B8%B02-%EC%9D%B4%EB%A6%84%EA%B4%80%EB%A6%AC%EC%9E%90%EC%99%80-Lambda-%ED%95%A8%EC%88%98

수식 > 정의된 이름 > 이름관리자를 클릭한 다음 '새로 만들기' 버튼을 누른 후 이름에 빗변길이, 참조 대상에 =LAMBDA(밑변, 높이, SQRT(SUM(밑변^2,높이^2)))를 붙여 넣고, 확인 버튼을 누릅니다.

Lambda 함수를 사용한 새 이름 정의


그러면 아래와 같이 이름에 '빗변길이'가 추가되고, 참조 대상에 Lamba 수식이 입력되었습니다. 닫기 버튼을 누릅니다.

이름 관리자


그리고, D2셀에
=빗변길이(a2,b2)라고 입력하면 값이 5인데, 이름을 사용자 정의 함수처럼 사용해서 간단하게 수식이 입력되었습니다.

이름을 사용자 정의 함수처럼 사용한 예

 

다. 이름을 다른 통합 문서에 적용하기

이름 관리자는 동일한 통합 문서에서만 적용되는 것이므로 다른 통합문서에는 적용되지 않는 단점이 있습니다.

예를 들어, A1에서 C2셀까지만 복사해서 새 통합문서(통합 문서3)에 붙여 넣고 이름 관리자를 열어 보면 '빗변길이'란 이름이 없습니다.

이름의 적용 범위가 통합 문서이므로 원칙적으로 다른 통합문서에 적용되지 않음


그러나, 이름 관리자의 이름을 포함한 수식을 복사해서 새 통합 문서에 붙여 넣으면 수식뿐만 아니라 이름 관리자의 이름도 복사되니 참고 바랍니다.

예를 들어, A1에서 C2까지 복사하지 않고, D2셀만 복사해서 새 통합문서(통합 문서2)에 붙여 넣어도 아래와 같이 이름 관리자에 사용자 정의 함수 빗변길이가 추가됩니다.

이름이 포함 된 셀을 다른 통합 문서에 복사시 이름까지 복사되어 다른 통합 문서에 해당 이름이 표시됨

 

시트 전체를 새 통합 문서에 복사해도 

 

당연히 이름도 같이 복사됩니다.

 

 

2. 주소에서 원하는 부분만 발췌하기

 

가. 논리 만들기


(1) 전체적인 구성
주소에서 공백으로 구분되는 부분을 선택적으로 추출하기 위해서는
먼저 몇 번째 공백인지와 그 위치를 알아야 합니다.
그러면 Mid 함수를 이용해서 시작위치와 개수를 지정해서 원하는 문자를 가져올 수 있습니다.


(2) 공백에 대한 위치 알아내기
첫 번째 공백의 위치는 find(" ", within_text, 1)로 구하는데,
두 번째 공백의 위치는 첫 번째 공백 위치에 1을 더한 다음부터 공백을 찾으므로
find(" ", within_text, find(" ", within_text, 1)+1),
세 번째 공백의 위치는 두 번째 공백 위치에 1을 더한 다음부터 공백을 찾으므로
find(" ", within_text, find(" ", within_text, find(" ", within_text, 1)+1)+1)이 됩니다.

위 구문들을 잘 살펴보면 두 번째 공백의 위치를 구할 때는 첫 번째 공백의 위치에 1을 더하므로
find(" ", within_text, 1)를 find_text로 대체하고
앞에 find(" ", within_text, 를 붙이고, 뒤에 +1을 붙이면
find(" ", within_text, find_text+1)이 되고,

세 번째 공백의 위치는 두 번째 공백의 위치에 1을 더하므로
find(" ", within_text, find(" ", within_text, 1)+1)를 find_text로 대체하고,
앞에 find(" ", within_text, 를 붙이고, 뒤에 +1을 붙이면
마찬가지로 find(" ", within_text, find_text+1)이 됩니다.

따라서, 이것을 정리하면 공백의 위치가 늘어날 때마다
이전 공백을 찾는 수식을 find_text로 대체하면 된다는 논리가 됩니다.

이것을 재귀 호출을 이용해서 만들 수 있습니다.

(3) 공백을 나타내는 순번이 0 이하이거나 공백의 개수보다 많을 때 처리
물론 공백을 나타내는 순번을 마이너스로 입력할 가능성은 낮지만 혹시나 몰라 0을 처리하면서 같이 0 이하일 때는 문자의 시작 위치를 1로 정합니다.

또한 공백의 개수가 3개인데, 4개 이상의 숫자를 입력한 다면
글자의 길이를 반환하도록 해야 합니다.

나. Lambda 수식 만들기


(1) 작성된 수식
좀 복잡한데 위 논리를 적용해서 Lambda 수식을 만들면 아래와 같습니다.
  * notepad++ 등 에디터에서 작성하는 것이 편리합니다.

=LAMBDA(within_text, find_text, ord_num,
	if(ord_num<=0,1,
		IF(ord_num=1,
			FIND(" ",within_text,find_text+1),
			if(ord_num>(len(within_text)-len(substitute(within_text," ",""))),
				len(within_text)+1,
				find_pos(
					within_text,
					FIND(" ",within_text, find_text+1),
					ord_num-1
				)					
			)	
		)		
	)	
)


이름 다시 말해 사용자 정의 함수에서 자기 자신을 호출(재귀 호출) 해야 하기 때문에 수식으로는 어렵고, 이름 관리자를 이용해서 Lambda 수식을 지정해야 합니다. 위에서는 수식을 이해하기 쉽게 여러 줄로 작성했지만 참조 대상에 붙여 넣으면 한 줄로 되고, 탭도 공백으로 변환됩니다.


(2) 수식의 이해
=LAMBDA(within_text, find_text, ord_num,

Lambda함수의 매개 변수는 within_text(검색 대상 텍스트), find_text(find 수식을 저장할 변수명)와 ord_num(순번) 3개입니다. 재귀 호출할 때도 3개의 변수를 전달해야 합니다.

if(ord_num<=0,1,
IF(ord_num=1,
FIND(" ",within_text,find_text+1),
if(ord_num>(len(within_text)-len(substitute(within_text," ",""))),
len(within_text)+1,
find_pos(
within_text,
FIND(" ",within_text, find_text+1),
ord_num-1
)
)
)
)

위 문장이 공백의 위치를 반환하는 계산식인데, If함수를 여러 번 시용해서 복잡하고, 중간에 이름과 동일한 find_pos를 호출하고 있습니다.
엑셀은 대소문자를 구분하지 않기 때문에 함수명 if가 IF로도 입력되어 있습니다.

if(ord_num<=0,1,

공백의 순번이 0인 경우는 텍스트의 첫 번째인 경우이므로 1을 반환합니다. 혹시 몰라서 마이너스를 입력하더라도 1로 하도록 ord_num<=0으로 작성했습니다.

IF(ord_num=1,

if(ord_num<=0,1, 다음에 입력되므로 value_if_false에 해당하는 부분입니다.
다시 말해 0보다 크다면인데, 다시 if함수가 있으므로 'ord_num이 1이라면'이 됩니다.

FIND(" ",within_text,find_text+1),

이 문장은 ord_num이 1일 경우 반환하는 값에 해당하는 부분입니다.
Find함수를 이용해 첫 번째 공백의 위치를 찾는 것인데,

위에서 살펴본 바와 같이 반복적으로 이전에 사용한 공백을 구하는 함수문을 입력해야 하기 때문에 find_text로 대체한 것입니다.
그러나, 첫 번째 공백을 찾을 때는 find_text+1이 1이 되어야 하므로 find_text를 0을 입력해야 하며,
두 번째 공백을 찾을 때부터는 3줄 아래 find_pos 함수로 find_text문이 만들어집니다.

if(ord_num>(len(within_text)-len(substitute(within_text," ",""))),
....
....
....
)

이 부분은 ord_num이 1이 아닐 경우에 대한 반환 값을 정의하는 부분입니다.

if함수가 중첩적으로 사용되기 때문에 복잡하고, 따라서, 알아보기 쉽도록 탭을 넣었습니다.

if함수의 조건은 ord_num이 len(within_text)-len(substitute(within_text," ","")))보다 클 때인데

len(within_text)는 Len(길이를 구해주는 함수) 함수 안에 within_text가 들어가 있으므로,
within_text 문자열의 개수를 구하는 것이고,

len(substitute(within_text," ",""))에서 Substitute함수는 문자열을 대체하는 함수로
substitute(within_text," ","")는 within_text 문자열에 있는 " "(한 칸 공백)을 모두 ""(공백)으로 바꾸라는 것입니다.
그런 다음 다시 Len(길이)를 구해줍니다.

결과적으로 공백이 포함된 길이에서 한 칸 공백이 제거된 문자열의 길이를 빼므로 한 칸 공백의 개수가 구해집니다.

따라서, if함수의 조건은 ord_num이 '한 칸 공백의 개수보다 클 때는'이 됩니다.

len(within_text)+1,

len(within_text)는 within_text 문자열의 길이를 반환하는데,
ord_num이 공백의 개수보다 크다면 문자열의 길이에 1을 더해줘야 합니다.
왜냐하면 공백의 위치에서 이전 공백의 위치를 뺀 후 -1을 하기 때문입니다.

find_pos(
within_text,
FIND(" ",within_text, find_text+1),
ord_num-1
)

이름 속에 이름이 들어 있으므로 재귀호출하는 부분인데,
인수를 Lambda함수의 매개 변수처럼 within_text, find_text, ord_num을 입력하는데,

within_text는 같은데,

find_text는 FIND(" ",within_text, find_text+1)로 이전에 사용한 공백을 구하는 함수문을 의미하는 find_text 앞에 Find(" ", within_text, 를 붙이고, 뒤에는 +1)을 붙여서 만듭니다. 반복할 때마다 find_text 문이 길어지게 됩니다.

ord_num-1은 ord_num이 1일 때까지만 처리하도록 1을 차감한 값을 대입합니다.

그리고, 1이 되면 위 수식 두 번째 줄 if(ord_num=1을 만족하므로
위 수식 중 세 번째 줄 FIND(" ",within_text,find_text+1)를 반환하는데,
겉으로 보면 같은 수식이지만 find_pos가 호출될 때마다 find_text문이 누적되므로 그것을 기준으로 한 값이 반환됩니다.

다시 말해 두 번 호출되면 find(" ", within_text, find(" ", within_text, 1)+1)이,
세 번 호출되면 find(" ", within_text, find(" ", within_text, find(" ", within_text, 1)+1)+1)이 반환됩니다.

)
)
)
)

if 함수를 닫아주는 괄호입니다.
괄호의 개수가 부족하면 에러가 발생하고, 위치가 다르다면 엉뚱한 결과가 나올 수 있으므로 주의해야 합니다.

(3) 적용 값


(가) find_pos 함수식 입력
i2셀에 이름(사용자 정의 함수)을 입력하기 위해 =fi까지 입력하면 fi로 시작하는 함수명이 표시되는데 5번째에 find_pos 함수명이 표시됩니다. find_pos를 마우스로 더블 클릭하거나 아래 화살표키를 눌러 이동한 후 탭키를 눌러 find_pos를 입력합니다.

find_pos 사용자 정의 함수


그리고, 첫 번째 인수로 F2셀을 지정하는데 오른쪽으로 복사할 때 F열만 변하지 않도록 $를 붙여서 $F2(F4키 3번 눌러서 입력 또는 키보드에서 $ 입력)로 입력했고,

두 번째 인수는 find_text이므로 의미로는 Find구문이지만,
첫 번째로 한 칸 공백의 위치를 구할 때는 Find함수의 세 번째 인수가 1이어야 하는데
Find함수식이 FIND(" ",within_text, find_text+1)로서 세 번째 인수가 find_text+1이므로 find_text는 0이어야 합니다.

그리고 세 번째 인수 ord_num(공백의 순번)는 시작 순번이 있는 G2셀을 입력한 것입니다.

그러면 첫 번째 한 칸 공백의 위치 6이 구해집니다.

i2셀의 채우기 핸들을 오른쪽으로 끌면 j2셀에 수식이 복사되는데,
=find_pos($F2,0,H2)로서, $F2는 변하지 않고, G2만 수식이 오른쪽으로 이동했으므로 H2로 변경되었습니다.

(나) 공백 사이의 문자열 추출
공백 사이의 문자열을 추출할 때는 Mid(dle) 함수를 사용하는데,
구문이 Mid(문자열, 시작위치, 개수)이므로,

문자열은 F2셀이 되고,
시작위치 시작 위치인 6을 이용하는데 공백 다음부터 가져와야 하므로 i2+1이 됩니다.
그리고, 개수는 끝 위치에서 시작위치를 뺀 후 다시 1을 빼야 합니다.
다시 말해 j2-i2+1입니다.

따라서 완성된 수식은 =MID(F2,I2+1,J2-I2-1) 입니다.

(다) 2행의 수식을 3행에 복사하기
i2셀부터 K2셀까지 마우스를 끌어서 선택한 후 K2셀의 채우기 핸들을 아래로 끌면


수식이 모두 복사됩니다.


여기서 살펴볼 것은 끝 순번 3에 대한 위치 값 J2셀 13입니다.
세 번째 공백이 없기 때문에 위 수식에서 len(within_text)+1이 반환되는데, F2셀의 문자열 길이 12(L2셀)에


1을 더한 값 13(J2셀)이 반환된 것입니다.

1을 더하지 않으면 산5-8로 마지막 한 글자가 나오지 않습니다.

Lambda함수(여러 개 매개변수)(완성).xlsx
0.01MB

 

반응형