흔한생각 (recording)/Dynamo

다이나모에서 ReplaceByCondition 활용 방법

hnanmal 2022. 5. 22. 00:05
300x250

리스트의 원소를 치환하고 싶어졌다

 

다이나모 노드 중에서 리스트 중 특정 원소를 치환하는 노드가 있습니다.

하나는 ReplaceItemAtIndex노드이고 다른 하나는 ReplaceByCondition노드입니다.

보통 이해하기 쉬운 노드는 ReplaceItemAtIndex 노드입니다.

 

 

 

먼저 ReplaceItemAtIndex 노드를 써서 치환해보자

 

이유는, 사용법이 좀 더 직관적이기도 하고, index만 건드리면 되기 때문에, 하드 코딩의 형식으로 원하는 인덱스만 직접 지정해서 치환하는 등의 활용도 가능하기 때문입니다.

 

그런데 한 번에 하나의 인덱스만 치환해주는 단점이 있어서, 한 리스트의 여러 개의 원소를 동시에 치환하고 싶으면 좀 노드 처리를 지저분하게 해야 합니다.

 

또 어떤 조건을 만족하는 원소들의 인덱스를 뽑아내어 처리하는 과정도 노드가 좀 길어지기 마련이라서, ReplaceItemAtIndex노드는 안 그래도 좁은 캔버스를 더욱 빽빽하게 만드는 원흉 노드이기도 합니다.

 

 

위의 코드를 보면 이해가 가실 겁니다.

 

이 코드의 목적은 Target List라고 적힌 가장 좌측의 리스트 원소 중에서 짝수만 골라서 “even”이라는 문자열로 치환하려고 하는 것인데요.

 

막상 마지막 결과값을 보면,

 

 

Target List에서 0번 인덱스만 치환한 리스트,

Target List에서 2번 인덱스만 치환한 리스트,

Target List에서 4번 인덱스만 치환한 리스트,

Target List에서 6번 인덱스만 치환한 리스트,

Target List에서 8번 인덱스만 치환한 리스트, …..

 

 

이런 식으로 결과를 만들어 놓았습니다. 속 터지죠?

 

원하는 형식의 결과를 얻으려면 다음과 같이 코드를 추가해야 합니다.

 

 

 

과정을 설명하자면

 

중첩리스트의 구조를 행렬로 보고,

행과 열을 전치시키는 List.Transpose 노드를 쓴 다음,

행렬이 바뀐 구조에서 Unique Items를 찾아서,

숫자 하나만 있는 경우와, 숫자와 “even” 문자열이 함께 있는 리스트가 나오면,

even 문자열이 항상 마지막 원소가 되도록 sorting 해주고,

List.LastItem노드를 써서 마지막 원소들만 골라내면… 헉헉

 

드디어 원하는 대로 짝수만 “even” 문자열로 치환된 문자열이 반환됩니다!

그런데 너무 길죠?

 

 

 

고작 원소 몇 개 치환하는 코드가 이렇게나 길어질 일인가 싶습니다.

그래서 이런 짓을 하지 말라는 뜻에서, 다이나모에서는 다른 노드 하나를 더 준비해둔 건지도 모르겠습니다.

 

 

 

ReplaceByCondition노드를 써서 동일한 작업을 해볼까?

 

이번에는 ReplaceByCondition노드를 써서 동일한 코드를 짜 봅시다.

 

 

짜잔, 엄청 짧죠?

아니 이렇게 짧게 처리되면, 아까 ReplaceItemAtIndex노드를 도대체 왜 쓰나 싶어요.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

함수를 값으로 전달? 함수??

 

그런데 이 ReplaceByCondition노드를 사용하려면 다이나모에서 Function을 만드는 개념에 조금 익숙해져야 합니다.

 

때문에 사용에 진입장벽이 있어서, 직관적으로 이해되는 ReplaceItemAtIndex노드로 좀 귀찮더라도 돌아가는 식으로 많이들 코드를 작성하는 거죠.

 

 

 

위 그림을 보시면, 좌측의 코드와 우측의 코드에 차이점이 보이실 겁니다.

 

좌측의 코드에서 “%”노드는 모든 입력 포트가 다 채워져 있지 않죠?

 

그래서 노드의 하단을 보면(빨간 점선) 반환 값이 우리가 일반적으로 보던 값이 아니고 “Function”이라는 객체로 반환되고 있다는 걸 볼 수 있습니다.

 

그에 반해 오른쪽 코드에서는 “%”노드의 모든 입력 포트가 채워져 있고, 그 결과로 각각의 수를 2로 나눈 나머지인 0과 1이 값으로 반환되고 있죠.

 

이렇게 함수를 만들어서 전달하는 이유는, ReplaceByCondition노드는 함수를 입력받아서 동작하는 노드이기 때문입니다.

 

 

좀 더 쉽게 설명하자면,

 

우리가 2로 나눈 나머지를 직접 전달하는 게 아니고,

 

“어떤 수를 2로 나눈 나머지”라는 규칙을 전달하면서, 어떤 수는 위쪽으로 따로 입력해 주는 것이죠.

 

그런데 여기까지 설명하면 질문이 나올 것 같습니다.

 

“입력해야 할 규칙이 복잡해지는 경우는 못쓰는 거 아닌가요? 함수를 만드는 방법이 노드를 꺼낸 뒤에 입력 포트에 일부만 입력하는 방법만 있다면 복잡한 규칙을 만들기 어려울 것 같은데요?”

 

 

 

함수와 함수를 합성하려면 Function Compose

 

 

당연히 복잡한 함수 객체를 만드는 방법이 있습니다. 이 역할을 하는 노드는

Function Compose라는 노드이고요.

 

 

 

위 그림처럼 Function Compose노드를 사용해서 2개 이상의 함수들을 하나로 합성해 버릴 수가 있습니다.

 

위 코드를 해석해보면,

 

“어떤 수를 2로 나누고 남은 나머지를 구하고, 그 나머지가 0과 같으면 True를, 0이 아니면 False를 반환하는 규칙”

 

이 된 것입니다. 이해되셨나요?

 

함수의 합성이기 때문에, 함수 합성의 순서에 따라 당연히 다른 함수가 됩니다.

 

따라서 % 노드를 function1 입력 포트에 연결하고, ==노드를 function0 입력포트에 연결하면 의도와는 다른 함수가 반환되니 주의해야 합니다.

 

 

 

다시 한번 최종 결과를 확인해봅시다. 구조도 단순하고, 결과도 명확하게 나오죠?

 

 

함수를 값으로 전달하는 개념에 익숙해지면, 이런 식으로 코드를 더 컴팩트하게 짤 수 있습니다.

 

 

 

다만 여러 명이 공유하고 Develop 하는 코드라면, 의사소통의 중요성도 무시할 수 없으니, 적절하게 상황에 맞추어 취사선택하시기를 권해 드립니다.

 

 

예시로 작성한 코드는 아래에 첨부했으니 다운 받아서 좀 더 확인해보셔도 좋을 것 같습니다.

ReplaceByCondition 활용방법.dyn
0.06MB

반응형