2014-01-14 7 views
18

참고 : 나는이 문제를 멋지게 해결할 수 있다고 확신했기 때문에 lodash 아래에이 질문을했습니다. 지금Lodash : 여러 객체에서 하나의 객체 만들기 - 합치거나 재정의 속성

다른 사용자 역할과 권한을 설명하는 개체가 있습니다.

내가 (응용 프로그램 코드를하지만 문제 자체을 반영하지 않습니다 이) "과 같이"정의 10-15 역할 같은 것을해야합니다 :

var role1 = { 
    views: { 
     v1: {access: true}, 
     v2: {access: false}, 
     v#: {access: false} 
    } 
} 

var role2 = { 
    views: { 
     v1: {access: false}, 
     v2: {access: true}, 
     v3: {access: true}, 
    } 
} 

여러 역할을해야합니다 연결된 사용자; 그 예에서는 ['role1', 'role2']이 될 수 있으며이 중 하나는 모든 사용자 역할에 정의 된 모든 소품의 조합이 될 단일 permissions 개체를 구성해야합니다.

기본적으로 허용 목록 기반이며 모든 "true"속성은 false로 정의 된 모든 항목을 무시해야합니다. 따라서, 예상 된 결과가 있어야한다 :

permissions = { 
    views: { 
     v1: {access: true}, 
     v2: {access: true}, 
     v2: {access: true} 
    } 
} 

내가 미친 중첩 루프 여기

에 의존하지 않고 하나를 해결하는 방법을 너무 잘 모르겠어요 JSBin의 출발점입니다 : http://jsbin.com/usaQejOJ/1/edit?js,console

도움 주셔서 감사합니다!

답변

37

Lodash에는이 문제를 우아하게 해결하는 데 도움이되는 몇 가지 방법이 있습니다.

우선, merge 방법. 여러 소스 객체를 사용하고 속성을 대상 객체에 재귀 적으로 병합합니다. 2 개의 객체가 같은 프로퍼티 명을 가지는 경우, 후자의 값은 전의 프로퍼티 명을 오버라이드 (override)합니다.

이것은 거의 우리가 원하는 것입니다. 당신의 역할 객체를 하나의 객체로 병합합니다. 우리가 원하지 않는 것은 오버라이드 동작입니다. 우리는 true 값이 항상 false을 무시하도록합니다. 운 좋게도 사용자 정의 병합 함수를 전달할 수 있으며 lodash의 merge은 두 개의 객체가 동일한 키를 가질 때 병합 된 값을 계산하는 데이를 사용합니다.

우리는 (대신 나중에 false 값이 true의를 오버라이드 (override) 할 수의.) 논리적으로 OR 항목 함께 사용자 정의 함수를 작성할 수 있습니다, 하나 값이 true을 경우 결과 병합 된 값이 true을되도록.

개체가 중첩되어 있으므로 사용자 지정 병합 함수가 부울 값을 비교할 때 OR 만 지정해야합니다. 객체를 비교할 때 우리는 그들의 속성을 정상적으로 병합하기를 원합니다 (다시 한번 사용자 정의 함수를 사용하여 병합을 수행합니다).

function do_merge(roles) { 

    // Custom merge function ORs together non-object values, recursively 
    // calls itself on Objects. 
    var merger = function (a, b) { 
    if (_.isObject(a)) { 
     return _.merge({}, a, b, merger); 
    } else { 
     return a || b; 
    } 
    }; 

    // Allow roles to be passed to _.merge as an array of arbitrary length 
    var args = _.flatten([{}, roles, merger]); 
    return _.merge.apply(_, args); 
} 

do_merge([role1, role2, role3]); 

Lodash 하나의 다른 방법에서 도움이 : 그것은 다음과 같이 보입니다 당신은 _.merge 함께 병합 할 객체의 배열을 허용하지 않는다는 문서에서 확인할 수 있습니다; 당신은 그들을 인수로 전달해야합니다. 우리의 경우, 배열은 매우 편리 할 것입니다.

이 해결하기 위해, 우리는 당신이 배열로 인수를 전달하여 메소드를 호출 할 수 있도록 자바 스크립트의 apply 방법 및 배열을 중첩 포함 할 수 있습니다 배열을 취하는 Lodash의 편리한 flatten 방법을 사용합니다 - [1, [2, 3], [4, 5]]처럼 - [1, 2, 3, 4, 5]으로 병합합니다.

그래서 우리는 flatten ed 배열에서 필요한 모든 인수를 모은 다음 applymerge!

개체가 매우 깊게 중첩되어있는 경우 merger을 재귀 적으로 호출하는 스택을 오버플로 할 수 있지만 개체에 대해서는 정상적으로 작동합니다.

+3

와우 나는 그 대답을 잘 설명 할 수는 없어! 백만 감사드립니다! –

+2

OMG는이 답변에 많은 감사를드립니다! – fuzzyvagina