【问题标题】:Merge two arrays of dictionaries in javascript在javascript中合并两个字典数组
【发布时间】:2018-04-22 18:34:01
【问题描述】:

我有两个字典数组,看起来像这样:

var lat = [{key:"2017-09-20T11:51:32.000Z", value:50.7825333},{key:"2017-09-20T11:51:33.000Z", value:50.7826},...];
var lon = [{key:"2017-09-20T11:51:32.000Z", value:-1.3075833},{key:"2017-09-20T11:51:33.000Z", value:-1.3076},...];

您可能已经猜到一个是纬度数组和经度数组!

我想要一种优雅的方式将时间、纬度、经度合并到一个数组中。两个数组都包含相同的键(我应该检查一下是否总是这样!)。

var latLon = [{time:"2017-09-20T11:51:32.000Z", lat:50.7825333, lon:-1.3075833},...]

我已经将一些可行但不漂亮的东西放在一起(即迭代两个数组并附加到一个新数组),但感觉必须有一种更时尚的方式来使用 Object.assign 和一些不错的 lamdas。如果包含任何有用的方法,我也会使用 D3.js 库。

【问题讨论】:

  • 最好将您尝试过的代码添加到您的问题中。
  • 我在工作,没有太多时间来确保这是正确的,但您可以查看 lodash 和/或下划线的 zip 方法 -- lodash.com/docs/4.17.4#zip

标签: javascript arrays object dictionary d3.js


【解决方案1】:

您可以使用Array#map 方法生成新数组(假设两个数组的顺序相同)。

var lat = [{key:"2017-09-20T11:51:32.000Z", value:50.7825333},{key:"2017-09-20T11:51:33.000Z", value:50.7826}];
var lon = [{key:"2017-09-20T11:51:32.000Z", value:-1.3075833},{key:"2017-09-20T11:51:33.000Z", value:-1.3076}];


var res = lat
  // iterate over the first array
  .map(function(o, i) {
    // generate the array element
    // where get values from element and
    // get value from second array using
    // the index
    return {
      time: o.key,
      lat: o.value,
      lon: lon[i].value
    }
  })

console.log(res);

// with ES6 arrow function
var res1 = lat.map((o, i) => ({time: o.key, lat: o.value, lon: lon[i].value}))


console.log(res1);

仅供参考: 如果相关数组元素的顺序不同,则需要通过比较时间值从第二个数组中获取元素(您可以使用Array#find 方法)或者您可以生成映射对象的 hashmap。

Array#find方法:

var lat = [{key:"2017-09-20T11:51:32.000Z", value:50.7825333},{key:"2017-09-20T11:51:33.000Z", value:50.7826}];
var lon = [{key:"2017-09-20T11:51:32.000Z", value:-1.3075833},{key:"2017-09-20T11:51:33.000Z", value:-1.3076}];



var res = lat
  .map(function(o) {
    return {
      time: o.key,
      lat: o.value,
      // get object by using find method
      lon: lon.find(function(o1) {
        return o1.key === o.key;
      }).value
    }
  })

console.log(res);

// with ES6 arrow function
var res1 = lat.map(o => ({
  time: o.key,
  lat: o.value,
  lon: lon.find(o1 => o1.key === o.key).value
}))

console.log(res1);

使用哈希图进行引用的更有效方法:

var lat = [{key:"2017-09-20T11:51:32.000Z", value:50.7825333},{key:"2017-09-20T11:51:33.000Z", value:50.7826}];
var lon = [{key:"2017-09-20T11:51:32.000Z", value:-1.3075833},{key:"2017-09-20T11:51:33.000Z", value:-1.3076}];

// generate reference hashmap for getting 
// value using the datetime string
var ref = lon.reduce(function(obj, o) {
  // set reference
  obj[o.key] = o.value;
  // return the reference object
  return obj;
  // set initial value as an empty object
}, {});

var res = lat
  .map(function(o) {
    return {
      time: o.key,
      lat: o.value,
      // get value from generated reference object
      lon: ref[o.key]
    }
  })

console.log(res);

【讨论】:

    【解决方案2】:

    我会避免使用find(),如果有任何机会你会处理很多物品。 find() 需要在第二个数组中搜索 lat 中的每一项,效率不高。

    如果您在第一个循环上构建字典并在第二个循环上创建新数组,则可以使用单个 mapreduce 来执行此操作。

    这也允许latlon 数组的顺序不同。

    var lat = [{key:"2017-09-20T11:51:32.000Z", value:50.7825333},{key:"2017-09-20T11:51:33.000Z", value:50.7826}];
    var lon = [{key:"2017-09-20T11:51:32.000Z", value:-1.3075833},{key:"2017-09-20T11:51:33.000Z", value:-1.3076}];
    
    var obj = lat.reduce((a, c) => (a[c.key] = {time: c.key, lat:c.value}, a), {});
    var arr = lon.map(lon => Object.assign(obj[lon.key], {lon: lon.value}));
    
    console.log(arr);

    【讨论】:

    • 如果你有机会处理很多项目,我会避免使用 find()。实际上使用find,您将循环直到找到请求的对象,而使用您的实际代码,您将循环整个数组两次,一次使用reduce(),下一次使用.map(),所以我认为使用find() 会更高效。 ;)
    • @chsdk 你的答案中的find()map() 内,这意味着find() 会为lat 中的每个项目调用。如果有 100 个项目,则调用 find() 100 次。这比 2 个循环差得多。
    • 是的,我同意你的看法,如果有很多项目(BTW 100 不是那么大),但find() 会尽快找到object,无论如何理论上它更糟,但它们的实施是为了保证性能。但是如果对象在两个数组中的排序方式相同,那么所有这些问题都将被真正忽略。但无论如何不要从你提供的伟大解决方案中获取任何东西。 :)
    • 你正在使用 ES6 箭头函数,浏览器对这些函数的支持如何?
    • @Taurus caniuse.com/#feat=arrow-functions 看起来全球不到 80%。
    【解决方案3】:

    这是基于key 时间。假设没有相同的键/时间,那么您可以这样做:

    var lat = [{key:"2017-09-20T11:51:32.000Z", value:50.7825333},{key:"2017-09-20T11:51:33.000Z", value:50.7826}];
    var lon = [{key:"2017-09-20T11:51:32.000Z", value:-1.3075833},{key:"2017-09-20T11:51:33.000Z", value:-1.3076}];
    
    var obj = {}, arr = lat.concat(lon);
    
    arr.forEach(function(x){
        obj[x.key] ? obj[x.key]["lon"] = x.value : obj[x.key] = {lat: x.value, time: x.key};
    });
    
    var latlon = Object.keys(obj).map(function(x){
        return obj[x];
    });
    

    您正在连接 2 个数组以组成一个数组。然后,您将使用时间作为键创建字典(这是假设您没有两个 lats 和两个 longs 具有相同时间的地方)。既然您知道您首先获得的是 lats,那么您的下一个关键比赛应该是 lons。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-12
      • 2015-11-15
      • 2022-11-02
      • 2022-12-26
      相关资源
      最近更新 更多