对javascript上的数组感到困惑

时间:2016-10-02 05:17:25

标签: javascript arrays

我想基于另外两个数组创建下一个数组:

array1 = ['a', 'b']
array2 = [1,2,3]

我想创建下一个数组

newArray = [['a',1], ['a',2], ['a',3], ['b',1], ['b',2], ['b',3]]

这是我的代码:



    var test1 = ['a', 'b'];
    var test2 = [1,2,3], arr1 = [], arr2 = [];

    for(var i = 0; i < test1.length; i++){
       arr1 = [];
       arr1.push(test1[i]);
      for(var x = 0; x < test2.length; x++){
        if(arr1.length > 1)
        	arr1.pop();
        arr1.push(test2[x])
        arr2.push(arr1);
        
      }
    }

console.log("arr1:",JSON.stringify(arr1), "arr2:" ,JSON.stringify(arr2));
&#13;
&#13;
&#13;

但它返回第二个数组的最后一个元素。

[['a',3], ['a',3], ['a',3], ['b',3], ['b',3], ['b',3]]

为什么会这样?

8 个答案:

答案 0 :(得分:5)

关于数组长度的所有其他答案,以及类似的事情都是不对的。你得到3(或任何最后的值/长度)的唯一原因是因为数组是引用的,而functions,而不是for-loops创建词法范围。这是你听说'功能是javascript中的一等公民'的原因之一。这是一个经典的例子,并且经常在采访中,用来惹恼那些不熟悉javascript范围内的范围的开发人员。有一些方法可以修复它,包括在函数范围内包装循环内部,并传入索引,但我想建议一个更“以javascript为中心”的方法,那就是解决函数问题。 / p>

请参阅此示例(顺便提一下,这也是实现目标的明确方法。)

var test1 = ['a', 'b'];
var test2 = [1,2,3];
    
// this will iterate over array 1 and return
// [[ [a,1],[a,2],[a,3] ],[ [b,1],[b,2],[b,3] ]]
var merged = test1.map(function(item1){
    return test2.map(function(item2){
        return [item1, item2];
    });	
  });

//this is a slick way to 'flatten' the result set
var answer = [].concat.apply([],merged )
    
console.log(answer) //this is it.

函数()使范围 - 而不是'括号'{}。最简单的解决方法通常是使用函数来解决问题,因为它们会创建词法范围。例如,npm上最受信任的库,lodash就是基于此。我认为随着你的进步,你会逐日编写越来越少的循环,并使用更多功能。

关于js小提琴的工作示例: https://jsfiddle.net/3z0hh12y/1/

您可以在此处详细了解范围和闭包 https://github.com/getify/You-Dont-Know-JS/blob/master/scope%20%26%20closures/ch1.md

还有一件事:当你认为你想要一个循环js时,你通常需要Array.map() ,特别是如果你正在重新映射值。

答案 1 :(得分:0)

它的发生是因为一旦它的长度超过1,你就会从arr1中弹出元素,所以最后一个元素就是这一点。

试试这个:

&#13;
&#13;
var test1 = ['a', 'b'];
var test2 = [1,2,3];
var arr1 = [], arr2 = [];

for(var i = 0; i < test1.length; i++) {
    for(var x = 0; x < test2.length; x++) {
        arr1[arr1.length] = [test1[i], test2[x]];
    }
}
console.log(JSON.stringify(arr1));
&#13;
&#13;
&#13;

答案 2 :(得分:0)

你的问题在于第二个循环。因为你对ary1有一个引用,所以你在每个循环中都要写入值。

所以第一次循环你的数组会有

[['a',1]]

但是因为你只有一个对ary1的引用,你只是在编辑你刚推入ary2的值。

所以你得到这个:

[['a',2],['a',2]]

您可能认为您正在推送一个新阵列,但它实际上是完全相同的阵列!所以模式继续,你得到你所看到的结果。

答案 3 :(得分:0)

除了针对两个数组的固定样式的解决方案之外,您可以使用另一种方法来获得结果。您可以使用迭代和递归方法来获取可变长度的零件长度。

function combine(array) {
    function c(part, index) {
        array[index].forEach(function (a) {
            var p = part.concat([a]);
            if (p.length === array.length) {
                r.push(p);
                return;
            }
            c(p, index + 1);
        });
    }

    var r = [];

    c([], 0);
    return r;
}

console.log(combine([['a', 'b'], [1, 2, 3]]));
console.log(combine([['a', 'b', 'c'], ['1', '2', '3', '4'], ['A', 'B']]));
console.log(combine([['a', 'b', 'c'], ['1', '2', '3', '4'], [['A'], ['B']]]));
.as-console-wrapper { max-height: 100% !important; top: 0; }

答案 4 :(得分:0)

我想正确的功能方法可以通过单个衬垫reduce和嵌套的map duo来完成。

var arr = ['a', 'b'],
    brr = [1,2,3],
 result = arr.reduce((p,c) => p.concat(brr.map(e => [c,e])),[]);
console.log(JSON.stringify(result));

答案 5 :(得分:-1)

你的方法有点偏离,你最好采用这种方法(我认为这非常简单): DEMO

var array1 = ['a', 'b'],
    array2 = [1,2,3],
    nextArray=[];

for(var i=0, array1Length=array1.length; i < array1Length; i++){
    for(var x=0, array2Length=array2.length; x < array2Length; x++){
    nextArray.push([array1[i],array2[x]]);
  }
}

console.log(nextArray);

答案 6 :(得分:-1)

我修改了你的代码(但不是太多,我试图保持相同的方法)。解决方案是在内部循环中创建一个新数组(arr1)。否则,第一个正确的对['a', 1]将在下一个循环传递开始推送到arr2后被覆盖。

var test1 = ['a', 'b'];
var test2 = [1,2,3];
var arr2 = [];

for(var i = 0; i < test1.length; i++){
    for(var x = 0; x < test2.length; x++){
        var arr1 = [];
        arr1.push(test1[i]);

        if(arr1.length > 1){
           arr1.pop();
        }
        arr1.push(test2[x]);
        arr2.push(arr1);
    }
}

答案 7 :(得分:-1)

是的,这种方式比它需要的更复杂。您想要的结果称为Cartesian product,可以像这样生成:

&#13;
&#13;
const cartesianProduct = (a, b) => {
  const rv = [];
  a.map(ae => b.map(be => rv.push([ae, be])));
  return rv;
};

const array1 = ['a', 'b']
const array2 = [1,2,3]
console.log(JSON.stringify(cartesianProduct(array1, array2)));
&#13;
&#13;
&#13;

如果Javascript6有flatMap,那就更简单了:

 const cartesianProduct = (a, b) => 
    a.flatMap(ae => b.map(be => [ae, be]));
相关问题