[Cocoa] 키밸류 코딩 – 집합 연산

키밸류 코딩의 집합 연산자

키-밸류 코딩을 사용할 때, 키패스 중에 집합(배열이나 세트)가 있을 때 각각의 원소에 대해 특정한 연산 (갯수나 합계, 평균 등)을 바로 수행한 결과를 쉽게 얻을 수 있다. 이는 코딩의 양을 비약적으로 줄여줄 수 있는 방법이므로 적극 활용하도록 하자.

집합 연산자는 특별한 키패스로 valueForKeyPath:의 파라미터 중 일부로 들어가게 된다. 이 연산자는 @마크로 시작하게 되는데 연산자의 왼쪽은 집합 객체를 나타내는 키이고 오른쪽은 개별 원소의 프로퍼티를 나타내는 키이다.

keypathToCollection.@collectionOperator.keypathToProperty

@count를 제외한 모든 집합 연산자는 오른쪽 항을 반드시 명시해야 한다. 그리고 이 때 반환되는 값은 연산자에 따라 달라질 수 있다.

단순 연산자

@avg

@avg는 프로퍼티값들의 평균을 구한다. 이 평균값은 double 형으로 계산되고 NSNumber에 의해 래핑되어 반환된다. 우변이 nil인 경우에는 0으로 간주된다.

NSNumber *transactionAverage = [transactions valueForKeyPath:@"@avg.amout"];

위 코드는 transactions 배열 내의 원소들의 amount 값의 평균을 구해주게 된다.

@count

이 연산자는 객체의 개수를 반환한다. 이 연산자의 오른쪽에는 다른 키패스가 붙지 않는다.

NSNumber *numberOfTransactions = [transactions valueForKeyPath:@"@count"];

@max

이 연산자는 배열의 원소중 최대값을 구한다. 이 때 비교하는 키는 compare: 메소드를 구현하고 있어야 한다. (스칼라 값에 대해서는 계산할 수 없음)

NSDate *latestDate = [transactions valueForKeyPath:@"@max.date"];

@min

반대로 배열의 원소의 키패스 중 최소값을 구한다.

NSDate *earliestDate = [transactions valueForKeyPath:@"@min.date"];

@sum

합을 구한다. 각각의 값은 double 형으로 캐스팅되어 계산되고, 계산 결과는 NSNumber로 반환된다.

NSNumber *amountSum = [transactions valueForKeyPath:@"sum.amount"];

객체 연산자

객체 연산자는 배열의 원소들의 특정 키로 구성된 집합을 얻는 방법이다.

@distinctUnionOfObjects

NSArray *payees = [transactions valueForKeyPath:@"@distinctUnionOfObjects.payee"];

위 코드는 개별 transaction 객체의 거래자 이름으로 구성된 배열을 반환한다. 이 때 중복된 이름은 제거하고 하나씩만 들어가게 된다. 중보글 허용하려면 @unionOfObjects 연산자를 쓰면 된다.

배열과 집합 연산자

만약 어떤 배열이 배열의 배열이라면 (혹은 NSSet의 배열) 원소가되는 각각의 배열의 각 원소에 대해서 한 번에 객체 연산자를 적용할 수 있다.

NSArray *allPayees = [arrayOfTransactions valueForKeyPath:@"distinctUnionOfArrays.payee"];

배열의 원소가 NSSet이라면 대신 다음 코드를 쓴다.

NSArray *allPayees = [arrayOfTransactions valueForKeyPath:@"distinctUnionOfSets.payee"];