使用 map 时使用扩展运算符扩展数组

Posted

技术标签:

【中文标题】使用 map 时使用扩展运算符扩展数组【英文标题】:Using spread operator to extend array when using map 【发布时间】:2016-06-12 19:55:56 【问题描述】:

我不确定这是否是正确的方法,但我很好奇它是否可以做到。我有一个对象,我需要从中创建一个数组,键是项,值 id 是它在数组中重复的次数。

const arrayInstructions = 
  'm': 5,
  's': 5,
  'p': 5

应该是['m','m','m','m','m','s','s' ... ]

这是工作方法:

var array = []
Object.keys(arrayInstructions).forEach(function (agenda) 
  array = array.concat( _.fill(Array(arrayInstructions[agenda]), agenda) )
)

可以这样做吗:

var deck = Object.keys(streamDeck).map(function (agenda) 
  var partial = _.fill(Array(streamDeck[agenda]), agenda)
  return ...partial // I know this is wrong
)

【问题讨论】:

不,不能。您正在寻找concatMap(JS 没有)。 考虑Object.keys(obj).reduce((s,k) => s+k.repeat(obj[k]), '').split('')。它做了无用的字符串连接,但很短。 【参考方案1】:

这里没有充分的理由使用扩展运算符吗?

在最简单的形式中,展开运算符允许您使用一个数组,其中需要多个“元素”或参数,例如

var part = [2, 3];
var arr  = [1, ...part, 4]; // [1,2,3,4]

这看起来确实很有用,但是您正在填充数组并将它们连接在一起,并且使用 concat 似乎更合适,但是如果您使用 apply 并返回一个地图

"use strict"

const arrayInstructions = 
  'm': 5,
  's': 1,
  'p': 2


var deck = [].concat.apply([], Object.keys(arrayInstructions).map(function(k)  
    return new Array(arrayInstructions[k]).fill(k) 
));


//output
document.body.innerhtml = '<pre>' + JSON.stringify(deck, 0, 4) + '</pre>';

【讨论】:

【参考方案2】:

您可以使用 Array.prototype.concat 上的 spread 来构建最终数组:

const arrayInstructions =  'm': 5, 's': 5, 'p': 5 ;

// This works because Array.prototype behaves like an empty list here
const deck = Array.prototype.concat(
  ..._.map(arrayInstructions, (times,agenda) => _.times(times, _=>agenda)) 
);

log(JSON.stringify(deck));

function log(x)  document.getElementsByTagName('pre')[0].appendChild(document.createTextNode(x)); 
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.5.1/lodash.js"></script>
<pre></pre>

更新

考虑到Bergi的建议,这个版本更短并且不依赖Array.prototype在数组上下文中的行为:

const deck = [].concat(..._.map(arrayInstructions,
    (times,agenda) => _.times(times, _=>agenda)
));

【讨论】:

不过我会推荐[].concat(... …) @Bergi 我也在考虑这一点,不知何故[].concat(...x) 感觉更健壮。你知道Array.prototype.concat(...x) 不起作用的具体场景吗? Array.prototype[0] = "gotcha" 将是灾难性的 :-) 诚然,这有点做作,但如果有人以类似的方式使用 Array.prototype.push(…) 【参考方案3】:

由于BergisaidJS没有concatMap,但是你可以手动定义这个功能:

function concatMap(array, func, thisArg) 
  return [].concat.apply([], [].map.call(array, func, thisArg));

concatMap(
  Object.keys(arrayInstructions),
  k => new Array(arrayInstructions[k]).fill(k)
);

【讨论】:

以上是关于使用 map 时使用扩展运算符扩展数组的主要内容,如果未能解决你的问题,请参考以下文章

扩展运算符...和map,filter等方法返回的数组是深拷贝么

扩展运算符

js_数组扩展

ES6---扩展运算符和rest‘...’(三点运算符),在数组函数set/map等中的应用

React 在使用扩展运算符更改状态时渲染,但在传递数组本身时不渲染 [重复]

扩展运算符的使用技巧