【问题标题】:Creating an Array based on an object基于对象创建数组
【发布时间】:2016-05-27 22:41:01
【问题描述】:

我有一个对象,其中的值是整数。就像是: {猫:2,狗:1,鸟:4}

我想创建一个数组,其中对象中的键包含在数组中的次数与值相同。所以,在这种情况下: [“猫”、“猫”、“狗”、“鸟”、“鸟”、“鸟”、“鸟”]

键总是相同的,但值可能为零。

我可以看到一种方法 - 对于每个键,我可以检索值,然后将单词推送到数组中的次数。但这需要为我的每个键编写几行代码(其中的代码比本示例中的要多得多)。我试过寻找更清洁的解决方案,但没有运气。有什么建议吗?

【问题讨论】:

  • 我想不出比这更好的方法了。这不是一个常见的操作,所以没有内置的东西可以做到这一点。
  • 如果你使用像 underscore.js 这样的库,它可能会提供一个函数来将字符串推送 N 次,其中 N 是来自对象的值。
  • 您可以使用for in 循环遍历键。无需为每个键重复代码。
  • 注意对象是无序的。你可能会也可能不会总是得到相同的数组。
  • 谢谢各位。 for in 循环(如下所示)是我所需要的。顺序在这里并不重要。

标签: javascript arrays node.js


【解决方案1】:

演示:https://jsfiddle.net/81LxL1qt/1/

var obj = {cat: 2, dog: 1, bird: 4};

var results = [];

for (var key in obj)
  for (var i = 0, count = obj[key]; i < count; i++)
    results.push(key);

console.log(results);

【讨论】:

  • 你不需要那个obj.hasOwnProperty(key)检查
  • 谢谢!这与我的想法相同,但比我想出的要简洁得多。
【解决方案2】:

一种功能强大的方法是:

var obj = {cat: 2, dog: 1, bird: 4};
var arr = [].concat(...Object.keys(obj).map(key => Array(obj[key]).fill(key)));
console.log(arr);

基本上它的作用是,它 gets the keys 对象,然后 maps 每个键到数组 filled 与该键。然后使用.concat() 将得到的二维数组flattens 转换为一维数组。

补充阅读:Arrow functions(=&gt;)、Spread operator(...)

【讨论】:

  • 它其实并不是性能最高的,初学者也很难理解,所以只是炫耀一下..
  • @CristiPufu 这不是炫耀,而是教学 :) 如果我幸运的话,他们会查看每个部分的作用,然后他们就不再是初学者了 :) 这篇文章确实教了我也有一些技巧。 (尤其是 Oriol,这太棒了)
【解决方案3】:

使用立即执行的生成器表达式,

var obj = {cat: 2, dog: 1, bird: 4};
var output = [...function*() {
  for(var key of Object.keys(obj))
    for(var i=0; i<obj[key]; ++i)
      yield key;
}()];
console.log(output);

【讨论】:

  • 为什么不for(var key in obj)
  • @4castle 如果您也想迭代继承的属性,请使用for..in
  • 知道了,虽然我怀疑有继承的属性。这个问题提出了一个非常简单的对象。
  • 我喜欢你在the answer 上发布的问题,我用谷歌搜索了我的答案。很高兴认识你!
  • @4castle 是的,我也打算使用fillyield* new Array(obj[key]).fill(key)。但后来我认为这会分配不必要的数组,Bergi 已经在我以前的答案中抱怨过这个 XD
【解决方案4】:

使用 Lodash 函数 forOwn

var result = [];
_.forOwn({cat: 2, dog: 1, bird: 4}, function(value, key){
    result.push(...Array(value).fill(key));
});

【讨论】:

  • _.times 将函数作为第二个参数。 _.times(value, _.constant(key)) 虽然有效 :)
  • @4Castle 你是绝对正确的。不过,选择使用 Array.fill() 代替,因为第三个 lodash 函数有点矫枉过正。
【解决方案5】:

这就是我的做法;

var arr = ["cat", "cat", "dog", "bird", "bird", "bird", "bird"],
    obj = arr.reduce((p,c) =>  (p[c] = p[c] ? ++p[c] : 1 ,p) ,{});
console.log(obj);

好吧。现在是星期五晚上,我很快就会找到正确的...(ft. Sia)

var obj = {cat: 2, dog: 1, bird: 4},
    arr = Object.keys(obj).reduce((p,c) => p.concat((new Array(obj[c])).fill(c)) ,[]);
console.log(arr);

再次抱歉......我想现在一切都很好。

【讨论】:

  • 很好的解决方案!但是您解决了反向操作:(他们希望您的输出成为输入。
【解决方案6】:

如果您愿意,请提供一个快速的 lodash 解决方案:

function mapObjectToArray(obj) {
  var arr = [];
  _.forIn(obj, function(value, key) {
    _.times(value, function() {
      arr.push(key);
    });
  });
  return arr;
}

var petCt =  {'cat': 2, 'dog': 1, 'bird': 3, 'ocelot': 0, 'sugar glider': 1};

<!DOCTYPE html>
<html>

  <head>
    <script data-require="lodash.js@4.6.1" data-semver="4.6.1" src="https://cdn.jsdelivr.net/lodash/4.6.1/lodash.js"></script>
    <link rel="stylesheet" href="style.css" />
    <script src="script.js"></script>
  </head>

  <body>
    <pre id="resultArray"></pre>


  <script>
    var petCt =  {'cat': 2, 'dog': 1, 'bird': 3, 'ocelot': 0, 'sugar glider': 1};
    
    function mapObjectToArray(obj) {
      var arr = [];
      _.forIn(obj, function(value, key) {
        _.times(value, function() {
          arr.push(key);
        });
      });
      return arr;
    }
    
    var elem = document.getElementById('resultArray');
    elem.innerHTML = mapObjectToArray(petCt);
    
  </script>
  
  </body>
</html>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-09-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多