ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [UiPath] Linq 및 람다식을 이용해 두 테이블을 비교하는 조건 예시
    UiPath RPA/Tips 2021. 3. 21. 12:50
    반응형

    UiPath 포럼에서 아래와 같은 문의가 있었습니다.

    forum.uipath.com/t/topic/298138?u=ddochea

     

    테이블과 테이블 사이

    1번 테이블에 들어있는 정보 와 2번테이블의 들어있는정보를 비교하고싶습니다. 예시로 1번 테이블 숫자라는 칼럼에 1,2,3,4 가 있고 2번테이블 숫자 라는 칼럼에 2,3,4,5 가 있으면 2,3,4가 중복되잖

    forum.uipath.com

    두 개의 테이블정보의 특정 컬럼에 1개라도 같은 값이 있는지 여부를 판단하는 방법인데, 단순 필터링이라면 액티비티가 존재하지만, 이 경우는 1개라도 있으면 중복여부를 true, false로 반환해야 하기 때문에 닷넷의 coding을 이용해야 할 것으로 보입니다.

     

    해결 예제는 포럼에 올렸으며, 문의주신 유저분이 "Solved Post"로 고정시켰으니 바로 찾으실 수 있으실 겁니다. 이번 포스트에서는 예제소스에 대한 분석위주로 작성합니다.

     

    Invoke Code를 분석하면 아래와 같이 3줄의 코드와 3개의 인수설정이 있습니다.

     Dim rows1 As IEnumerable(Of Object) = table1.AsEnumerable().Select(Function(r) r.ItemArray(0))
     Dim rows2 As IEnumerable(Of Object) = table2.AsEnumerable().Select(Function(r) r.ItemArray(0))
     IsContains = rows1.Any(Function(t1) rows2.Contains(t1))

     

    인수설정

    인수에 대해 잘 모르신다면 ddochea.tistory.com/55 를 참조해주세요. "해당 소스코드에서 비교할 테이블 변수 table1, table2 입력과 결과를 담기위해 출력 설정한 IsContains변수가 구성되어있다." 정도로만 넘어가시면 될 듯 합니다.

     

    소스코드 맨 첫번째 줄 부터 분석해보겠습니다.

    1번째 줄

     Dim rows1 As IEnumerable(Of Object) = table1.AsEnumerable().Select(Function(r) r.ItemArray(0))

    1. AsEnumerable()

    시작부터 난관이죠? 😅 해당 소스는 table1 변수를 AsEnumerable() 함수를 써서 "IEnumerable"이라는 이름을 가진 배열형식으로 만드는 함수입니다.  IEnumerable에 대한 자세한 설명은 포스트 하단에 참조링크를 걸어두겠습니다. Array, List와 같은 배열형식을 대표하는 "구조형태" 생각하면 될 것 같습니다.

    ( * 구조형태라고 작성하니 이것도 어렵게 느껴지긴 하는데 정식명칭으론 "인터페이스(interface)"라고 합니다.  객체지향 개발언어에선 거의 필수적으로 존재하는 개념이자 형식이므로 시간되실때 찾아보시기 바랍니다 😅)

     

    그럼 왜 AsEnumerable() 함수를 사용하여 IEnumerable 형식으로 바꿨을까요? 바로 다음에 호출하는 함수인 Select을 사용하기 위함입니다.

    2. Select()

    Select() 은 해당 배열의 각 요소 중, 필요한 요소를 "선택"하는 함수입니다. 예를 들어 아래와 같이 이름, 성별, 학년 정보가 있는 학생의 정보를 배열로 담은 "Students" 라는 이름의 리스트가 있다고 가정해보겠습니다.

    이름 성별 학년
    홍길동 1학년
    홍길순 1학년
    김철수 2학년

    여기서 이름만 따로 뽑고싶을때, 아래와 같이 작성하게 됩니다.

    Students.Select(Function(student) student.이름)

    예제 소스에서도 비교하고자하는 열만 선택하기위해 Select 함수를 사용했습니다. 테이블 변수를 배열화시키면 EnumerableRowCollection 형식으로 변하게 되는데, Collection에 포함된 각 Row 값은 ItemArray라는 배열을 가지고 있습니다. 해당 배열은 각 Row에 있는 컬럼(Column) 값을 가지고 있는데, 예시는 가장 왼쪽에 위치한 0번째 컬럼값으로 비교하는 것이기 때문에 ItemArray(0)을 입력하게 된 것입니다.

     

    Select() 함수 및 이어서 설명하게될 Any() 함수는 System.Linq 네임스페이스내 정의되어 있기 때문에 UiPath 메인화면 가져오기 기능을 통해 네임스페이스를 정의해야 합니다.

    가져오기 기능이 위치한 자리

    Select() 함수 내 함수가 또 존재하는데 이 함수를 "람다식"이라고 부릅니다. 람다식에 대한 특징은 바로 이어서 설명드릴 Any() 및 Contians() 함수에서 다루겠습니다.

     

    1번째 소스가 모두 동작하면, rows1 변수에 "1,2,3,4"로 구성된 IEnumable 배열이 존재하게 됩니다.

    2. 세번째 줄

     IsContains = rows1.Any(Function(t1) rows2.Contains(t1))

     

    두번째 줄 코드도 같은 내용이니, 바로 세번째 줄 코드를 설명드리겠습니다.

    3. Any()

    Any() 함수는 람다식을 통해 작성한 조건이 1개라도 맞으면 true, 모두 해당안되는 경우 false를 반환하는 함수입니다. 

    4. Contains()

    배열 안에 포함되는 요소가 존재하면 true, 없으면 false를 반환하는 함수입니다. 예를 들어, ["홍길동","홍길순","김철수"] 3개의 요소가 들어간 "학생이름리스트"라는 배열에 아래와 같이 코드를 작성하면 각각 true, false 결과를 얻게됩니다.

    학생이름리스트.Contains("홍길동")) // 포함되어 있으므로 true
    학생이름리스트.Contains("김영희")) // 포함되어 있지않으므로 false

    그런데 이번예제는 1개의 리스트에서 1개의 요소를 비교하는것이 아닌, 2개의 리스트간 포함여부를 비교하는 함수입니다. 따라서 모든 요소를 비교하기위해 반복적인 행위를 거쳐야 합니다.

     

    Linq 함수에서 람다식은 이런 반복적인 행위(Function) 자체를 변수처럼 대입시켜서 사용하는 것을 의미합니다. Any 함수에 선언된 람다식 Function(t1) rows2.Contains(t1) 는 rows1에 있는 요소 1,2,3,4를 모두 "t1"이라는 명칭을 가진 내부 람다식 함수에 대입시켜 완료할때 까지 반복하게 됩니다.

    // [1,2,3,4] 4개 요소를 가진 row1의 Any 함수 내부에서 동작하는 Contains
    
    false = Function(t1) rows2.Contains(1) // t1에 1 대입
    true = Function(t1) rows2.Contains(2) // t1에 2 대입
    true = Function(t1) rows2.Contains(3) // t1에 3 대입
    true = Function(t1) rows2.Contains(4) // t1에 4 대입

    4개의 요소를 모두 비교하고 나면, true 가 1개라도 있는지 확인해 최종적으로 IsContains 변수에 대입시켜줍니다. Foreach에 대한 액티비티 및 개념을 아신다면, 람다식은 함수 안에 생성하는 Foreach라는 개념이라 생각하면 이해하기 쉬우실 것입니다. 🤗

     

     

     

    참조 : docs.microsoft.com/ko-kr/dotnet/api/system.collections.generic.ienumerable-1?view=net-5.0

     

     

    반응형

    댓글

Designed by Tistory.