【问题标题】:Dynamic nested for loops to be solved with recursion用递归解决的动态嵌套for循环
【发布时间】:2014-11-02 19:59:08
【问题描述】:

我试图得到一个看起来像这样的结果: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);
      });
   });
});

输出是一个数组(类别),其中包含限制数组的所有可能组合。

现在,我的问题是我需要一种方法来处理未知数量的限制数组。 我对正确解决方案的猜测是 recursionBUT 我无法产生任何真正有效的东西,因为我还不能把头绕在递归上:)

可以在此处找到使用一些测试数据准备的小提琴:jsFiddle。 fiddle 使用 angular 进行一些简单的数据绑定和调试结果输出,使用 underscorejs 处理数组。

【问题讨论】:

  • 尽量不要使用副作用(即pushing 到全局categories 数组),而是在每个步骤中使用return 并使用map(和flatten
  • 嗯.. 好吧。 Flatten 在这里没有任何用处,因为我需要来自不同数组的不同值的组合。但是 map 可能是一些东西..即使我看不到它如何解决我面临的动态数组数量的问题。您愿意详细说明吗?
  • 尝试使用map(即使以非通用方式),您将看到flatten 的用途。然后,创建一个函数,获取groups、当前组的索引(“嵌套级别”)和访问组的当前名称。基本情况(当嵌套级别达到groups 的长度时)将返回那些当前名称(由 ` | ` 连接),即递归情况 - 你会发现。

标签: javascript arrays recursion underscore.js nested-loops


【解决方案1】:

我最近编写了一个递归函数来创建数组的所有组合。您必须将数据转换为我的函数使用的数组数组,但这应该不难。

无论如何,这是带有可运行示例的代码:

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);
  }
}

【讨论】:

    【解决方案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

    【讨论】:

    • 对于我的具体情况,这完全是“开箱即用”的!为什么人们对此投反对票?我不知道如何动态使用它?将最终名称放在一起的函数需要特定数量的参数。谢谢!
    • 至少有人给了我一些信息。我会更新我的答案。谢谢。
    • 好东西!只需将 fn 调用更改为仅传递值数组而不是 fh.apply()。我认为做到了!再次感谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-19
    • 1970-01-01
    • 2018-08-12
    • 2018-01-11
    • 2014-10-01
    相关资源
    最近更新 更多