2014-11-02 4 views
5

다음과 같은 결과를 얻으려고합니다. Miniors | Boys | 54kg - 62kg 모든 값은 파이프로 구분됩니다. 특정 "제한 유형"을 포함하는 배열에서 온 것입니다. 예 : ageGroups, genders, weightClasses (위 참조).동적으로 중첩 된 루프가 재귀를 통해 해결되도록

내가 지금이 결과를 얻을 수있는 방법은 중첩 된 forEach 루프 (underscorejs 사용)를 하드 코드하는 경우입니다. 그러나 이것은 내가 원하는 결과를 얻으려면 루프를 몇 개 배열해야 하는지를 의미합니다. . 이 "미세"작동 :

var categories = []; 
_.each(ageGroups, function(ageGroup) { 
    _.each(gender, function(gender) { 
    _.each(weightClasses, function(weightClass) { 
     categories.push(ageGroup.name + ' | ' + gender.name + ' | ' + weightClass.name); 
     }); 
    }); 
}); 

출력은 제한 어레이의 모든 가능한 조합을 갖는 어레이 (카테고리)이다.

이제 내 문제는 알 수없는 제한 개수의 배열을 사용하여 동일한 작업을 수행 할 방법이 필요하다는 것입니다. 적절한 솔루션에 대한 내 생각은 재귀, 하지만 인 나는 아직 재귀 주위에 내 머리를 정리하기 :

바이올린 준비 할 수 아니에요 이후 실제로 작동 아무것도 생산할 수 없었다 일부 테스트 데이터는 여기에서 찾을 수 있습니다 : jsFiddle. 바이올린은 결과 출력의 간단한 데이터 바인딩 및 디버깅을 위해 각도를 사용하고 배열 처리를 위해 밑줄을 사용합니다.

+0

하지 시도 부작용 (예 : 전역'categories' 배열에'push ')을 사용하는 대신 각 단계에서'return'을 사용하고'map' (그리고'flatten')을 사용하십시오 – Bergi

+0

흠 .. 오키. Flatten 다른 배열에서 다른 값의 조합이 필요하기 때문에 여기에 어떤 용도로 사용하지 않을 수 있습니다. 그러나지도가 뭔가있을 수 있습니다 .. 어떻게 동적 인 양의 배열에 직면하고있는 문제를 해결할 수 있는지는 알 수 없지만. 정교하게 신경 쓰는거야? – aup

+0

'map'을 사용해보십시오 (비 일반적인 방식으로조차도). 그러면 여러분은'flatten'을 위해 필요한 것을 보게 될 것입니다. 그런 다음'groups', 현재 그룹의 인덱스 ("중첩 레벨") 및 방문한 그룹의 현재 이름을 사용하는 함수를 만듭니다. 네 스팅의 레벨이'groups'의 길이에 도달했을 때) 기본 케이스는 그 현재 이름 ('|'에 의해 합쳐진)을 반환 할 것입니다. 재귀 적 케이스 - 당신은 알아낼 것입니다. – Bergi

답변

2

최근 배열의 모든 조합을 만드는 재귀 함수를 작성했습니다. 내 함수에서 사용하는 배열 배열로 데이터를 변환해야하지만 어렵지는 않습니다. 여기

var v = [['Miniors','Kadettes','Juniors', 'Seniors'], ['Boys','Girls','Men','Women'],['54kg - 62kg','64kg - 70kg','71kg - 78kg','79kg - 84kg']]; 
 
var combos = createCombinations(v); 
 
for(var i = 0; i < combos.length; i++) { 
 
    document.getElementsByTagName("body")[0].innerHTML += combos[i] + "<br/>"; 
 
} 
 

 
function createCombinations(fields, currentCombinations) { 
 
    //prevent side-effects 
 
    var tempFields = fields.slice(); 
 

 
    //recursively build a list combinations 
 
    var delimiter = ' | '; 
 
    if (!tempFields || tempFields.length == 0) { 
 
    return currentCombinations; 
 
    } 
 
    else { 
 
    var combinations = []; 
 
    var field = tempFields.pop(); 
 

 
    for (var valueIndex = 0; valueIndex < field.length; valueIndex++) { 
 
     var valueName = field[valueIndex]; 
 

 
     if (!currentCombinations || currentCombinations.length == 0) { 
 
     var combinationName = valueName; 
 
     combinations.push(combinationName); 
 
     } 
 
     else { 
 
     for (var combinationIndex = 0; combinationIndex < currentCombinations.length; combinationIndex++) { 
 
      var currentCombination = currentCombinations[combinationIndex]; 
 
      var combinationName = valueName + delimiter + currentCombination; 
 
      combinations.push(combinationName); 
 
     } 
 
     } 
 
    } 
 
    return createCombinations(tempFields, combinations); 
 
    } 
 
}

+0

좋은 물건! 감사합니다. – aup

2
function iterate(lists, fn) 
{ 
    var values = []; 
    function process(listIndex) 
    { 
    var list = lists[listIndex]; 

    // no list? create the value 
    if (!list) 
    { 
     fn.apply(null, values); 
     return; 
    } 

    for (var i = 0; i < list.length; i++) 
    { 
     values[listIndex] = list[i]; 
     process(listIndex+1); 
    } 
    } 

    process(0); 
} 

질문에서 언급 한 데이터를 기반으로 작동하는 예는 다음과 같습니다 :

어쨌든, 여기에 실행 가능한 예제와 코드는 http://jsbin.com/boqucu/2/edit

+0

내 경우에는 완벽하게 "out-of-the-box"로 작동합니다! 사람들이 왜이 투표를하지 않습니까? 어떻게 내가 이것을 동적으로 사용할 수 있는지 보지 못합니까? 최종 이름을 결합하는 함수는 특정 양의 매개 변수를 필요로합니다. 감사합니다. – aup

+0

적어도 누군가 나에게 약간의 정보를 제공합니다. 나는 나의 대답을 업데이트 할 것이다. 감사. – lloiser

+0

굉장한 물건! fn-call을 단지 fh.apply() 대신 값 배열로 전달하도록 변경했습니다. 나는 그것을했다라고 생각한다! 다시 한 번 감사드립니다! – aup

관련 문제