如何在JavaScript中压缩两个数组?

use*_*od2 83 javascript arrays

我有2个数组:

var a = [1, 2, 3]
var b = [a, b, c]
Run Code Online (Sandbox Code Playgroud)

我想得到的结果是:

[[1, a], [2, b], [3, c]]
Run Code Online (Sandbox Code Playgroud)

这看起来很简单,但我无法弄清楚.

我希望结果是一个数组,两个数组中的每个元素都压缩在一起.

tew*_*hia 161

使用map方法:

var a = [1, 2, 3]
var b = ['a', 'b', 'c']

var c = a.map(function(e, i) {
  return [e, b[i]];
});

console.log(c)
Run Code Online (Sandbox Code Playgroud)

DEMO

  • @runawaykid答案是对的.您可以在回调参数上看到[MDN地图文档](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map#Parameters).参数是(按顺序):`currentvalue`,`index`,`array` (7认同)
  • 使用箭头符号甚至更好一点:var c = a.map((e,i)=> [e,b [i]]); (6认同)
  • 总的javascript noob在这里,但我的印象是索引必须在元素之前?也就是说.map(function(index,element))? (3认同)
  • 请注意,如果数组的长度不同,那么这将用未定义的值填充右侧(如果“a”更长),或者将省略一些条目(如果“b”更长)。 (2认同)

Rok*_*jan 14

Array.prototype.map() 旧版浏览器不支持

const a = [1, 2, 3],
      b = ['a', 'b', 'c'];

const zip = (arr1, arr2) => arr1.map((k, i) => [k, arr2[i]]);

console.log(zip(a, b)) // [[1, "a"], [2, "b"], [3, "c"]]
Run Code Online (Sandbox Code Playgroud)

这是一个适用于所有地方的替代方案

var a = [1, 2, 3],
    b = ['a', 'b', 'c'];

var zip = [];
for (var i = 0; i < a.length; i++){
   zip.push([a[i], b[i]]);
}

console.log(zip); // [[1, "a"], [2, "b"], [3, "c"]]
Run Code Online (Sandbox Code Playgroud)

  • 谢谢@RokoC.Buljan,很好。不过我认为应该是Math.min。zip 来自函数式语言(就像filter、map、reduce 等),它的主要目的是将两个流输入到一个二进制计算中。如果其中一个缺失,结果无论如何都是不确定的,因此我们应该尽早停止。此外,在 FP 中,流可能是无限的(!),这意味着上述算法永远不会停止。当然,使用 js 数组不是这样,但这仍然是经典的“zip”。(性能方面:想象一个数组有 100k 个项目,而另一个数组只有 12 个)。 (5认同)
  • **谢谢** @goteguru,我添加了两个不同长度数组的示例。 (3认同)
  • 优雅,但有缺陷。经典 zip 必须是可交换的,但此实现不是。检查不同长度的数组。 (2认同)

Mus*_*tor 9

利用生成器函数进行压缩

您还可以使用生成器函数zip().

const a = [1, 2, 3]
const b = ['a', 'b', 'c']

/**
 * Zips any number of arrays. It will always zip() the largest array returning undefined for shorter arrays.
 * @param  {...Array<any>} arrays 
 */
function* zip(...arrays){
  const maxLength = arrays.reduce((max, curIterable) => curIterable.length > max ? curIterable.length: max, 0);
  for (let i = 0; i < maxLength; i++) {
    yield arrays.map(array => array[i]);
  }
}

// put zipped result in an array
const result = [...zip(a, b)]

// or lazy generate the values
for (const [valA, valB] of zip(a, b)) {
  console.log(`${valA}: ${valB}`);  
}
Run Code Online (Sandbox Code Playgroud)
.as-console-wrapper { max-height: 100% !important; top: 0; }
Run Code Online (Sandbox Code Playgroud)

上面的方法适用于任意数量的数组,并且zip()最长的数组undefined将作为较短数组的值返回。

全部压缩Iterables

这里的函数可用于所有Iterables(例如MapsSets或您的自定义Iterable),而不仅仅是数组。

const a = [1, 2, 3];
const b = ["a", "b", "c"];

/**
 * Zips any number of iterables. It will always zip() the largest Iterable returning undefined for shorter arrays.
 * @param  {...Iterable<any>} iterables
 */
function* zip(...iterables) {
  // get the iterator of for each iterables
  const iters = [...iterables].map((iterable) => iterable[Symbol.iterator]());
  let next = iters.map((iter) => iter.next().value);
  // as long as any of the iterables returns something, yield a value (zip longest)
  while(anyOf(next)) {
    yield next;
    next = iters.map((iter) => iter.next().value);
  }

  function anyOf(arr){
    return arr.some(v => v !== undefined);
  }
}

// put zipped result in aa array
const result = [...zip(a, new Set(b))];

// or lazy generate the values
for (const [valA, valB] of zip(a, new Set(b))) {
  console.log(`${valA}: ${valB}`);
}
Run Code Online (Sandbox Code Playgroud)

显然,也可以仅使用[...Iterable]将 any 转换Iterable为数组,然后使用第一个函数。