【问题标题】:Javascript for/in loop - join items from two different objects?Javascript for/in 循环 - 连接来自两个不同对象的项目?
【发布时间】:2017-08-18 17:38:13
【问题描述】:

我在下面有这些数据集,我想合并每个集合中的数据:

    var data = {};
    var datasets = [
        {"_id":"58d6c806d7c80d5d44a35204","particles":{"timestamp":[1490470918708,1490470962915,1490470967186],"Particles":["108","108","109"]}},
        {"_id":"58d6caf62552b75f26f56f91","particles":{"timestamp":[1490471670888,1490473309103],"Particles":["109","100"]}}
    ];

    datasets.forEach(function(dataset, index) {
        for (var key in dataset.particles) {
            data[key] = dataset.particles[key];
        }
    });
    console.log(data);

结果:

{ timestamp: [ 1490471670888, 1490473309103 ],
  Particles: [ '109', '100' ] }

他们没有加入。我追求的结果:

 { timestamp: [ 1490470918708,1490470962915,1490470967186, 1490471670888, 1490473309103 ],
  Particles: [ '108','108','109', '109', '100' ] }

有什么想法吗?

编辑

concatpush 在处理非常大型数据时更快吗?

【问题讨论】:

  • 因为我看到了很多好的答案,所以我不会写我的。只是一个评论,我注意到很多人都在使用concat。这每次都会创建一个新数组,而不仅仅是在现有数组中添加新项目。我建议改用push
  • @Luka 的推送速度比 concat 快吗?
  • 一般push 使用Array.prototype.push.apply 调用会更快。但要小心,因为这种方式有限制:你不能以这种方式追加大量的项目。
  • @Luka 我需要推送大量数据。所以我认为 concat 更好?
  • 然后使用 concat 以确保安全。使用push 可能会破坏程序。

标签: javascript for-loop foreach for-in-loop


【解决方案1】:

您必须连接数组,而不仅仅是重新分配值。

var data = {};
var datasets = [
    {"_id":"58d6c806d7c80d5d44a35204","particles":{"timestamp":[1490470918708,1490470962915,1490470967186],"Particles":["108","108","109"]}},
    {"_id":"58d6caf62552b75f26f56f91","particles":{"timestamp":[1490471670888,1490473309103],"Particles":["109","100"]}}
];

datasets.forEach(function(dataset, index) {
  for (var key in dataset.particles) {

    // Check if key already exists.
    if( data[key] === undefined )
      data[key] = [];

    // Add current timestamps.
    data[key] = data[key].concat(dataset.particles[key]);
  }
});
console.log(data);

【讨论】:

    【解决方案2】:

    希望这是需要的:

    var data = {};
    var datasets = [{
        "_id": "58d6c806d7c80d5d44a35204",
        "particles": {
          "timestamp": [1490470918708, 1490470962915, 1490470967186],
          "Particles": ["108", "108", "109"]
        }
      },
      {
        "_id": "58d6caf62552b75f26f56f91",
        "particles": {
          "timestamp": [1490471670888, 1490473309103],
          "Particles": ["109", "100"]
        }
      }
    ];
    var output = {
    
    }
    datasets.forEach(function(dataset, index) {
      for (var key in dataset.particles) {
        if (typeof output[key] == 'undefined') {
          output[key] = []
        }
        //console.log(dataset.particles[key])
        for (var k of dataset.particles[key]) {
          output[key].push(k)
        }
    
      }
    });
    console.log(output);

    【讨论】:

    • 感谢您的回答!当涉及到非常大的数据时,是 concat 还是 push 更快
    • 似乎 concat 比从这里推送结帐要快得多jsperf.com/concat-vs-push-array/1
    【解决方案3】:

    函数式编程风格中,您可以使用reduceObject.keys

    var datasets = [
        {"_id":"58d6c806d7c80d5d44a35204","particles":{"timestamp":[1490470918708,1490470962915,1490470967186],"Particles":["108","108","109"]}},
        {"_id":"58d6caf62552b75f26f56f91","particles":{"timestamp":[1490471670888,1490473309103],"Particles":["109","100"]}}
    ];
    
    var data = datasets.reduce ( (acc, {particles}) =>
        Object.keys(particles).reduce ( (acc, key) =>
            (acc[key] = (acc[key] || []).concat(particles[key]), acc), acc
    ), {} );
        
    console.log(data);
    .as-console-wrapper { max-height: 100% !important; top: 0; }

    使用push 代替concat,以防性能问题:

    var datasets = [
        {"_id":"58d6c806d7c80d5d44a35204","particles":{"timestamp":[1490470918708,1490470962915,1490470967186],"Particles":["108","108","109"]}},
        {"_id":"58d6caf62552b75f26f56f91","particles":{"timestamp":[1490471670888,1490473309103],"Particles":["109","100"]}}
    ];
    
    var data = datasets.reduce ( (acc, {particles}) =>
        Object.keys(particles).reduce ( (acc, key) =>
            ((acc[key] = (acc[key] || [])).push(...particles[key]), acc), acc
    ), {} );
        
    console.log(data);
    .as-console-wrapper { max-height: 100% !important; top: 0; }

    但请注意,在此版本的代码中,push 将获取particles[key] 中的每个单独的数组元素作为参数,这占用了堆栈空间,而堆栈空间又是有限的。见"Is there a max number of arguments JavaScript functions can accept?"。您可以通过对particles[key] 中的每个单独元素执行单独的push 调用来克服此限制,但这会降低性能。所以最后你可能会更好地使用concat 版本。

    【讨论】:

    • 谢谢。这比连接非常大数据的 for 循环快吗?
    • 为什么不对您的数据进行测试呢?通常for 循环很快,但是如果您在这些循环中进行大量操作,那么数组方法有时会导致代码分配较少,然后可以更好地由引擎优化。这一切都取决于您的实际案例和数据。测试一下。
    • 我添加了push而不是concat的变体,但对于您的情况是否有性能差异确实有待测试。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-04
    • 2011-07-12
    • 2011-11-06
    • 2015-08-10
    相关资源
    最近更新 更多