通过唯一键组合对象数组

时间:2014-12-30 12:56:59

标签: javascript arrays underscore.js

我有两个对象数组。其中一人每天有访客数量,其他人每天有文件数。像这样:

var visitors =  [ { '2014.12.25': 141 }, { '2014.12.26': 630 }, { '2014.12.30': 71 } ];
var documents = [ { '2014.12.15': 31 }, { '2014.12.26': 60, }, { '2014.12.30': 95  } ];

每个数组的日期可能不同。 如何将数组转换为以下结构(意味着按日期键组合它们):

[ { date: '2014.12.15', visits: 0,   docs: 31 },   // here visits = 0 because there were no visitors at this date
  { date: '2014.12.25', visits: 441, docs: 0 },  // here docs = 0 because no docs were created at this date
  { date: '2014.12.26', visits: 630, docs: 60 },
  { date: '2014.12.30', visits: 71,  docs: 95 },    
]

允许使用的工具:JavaScriptUndescore.js

谢谢

3 个答案:

答案 0 :(得分:1)

让我们在原生JS中了解一下。

首先,让我们将这两个数组转化为更明智的对象:

function reduceDates(prev, curr){
    var date = Object.keys(curr)[0]; // This is why {date : value} makes no sense.
    prev[date] = curr[date];
    return prev;
}

var v = visitors.reduce(reduceDates, {});  // {2014.12.25: 141, 2014.12.26: 630, 2014.12.30: 71}
var d = documents.reduce(reduceDates, {}); // {2014.12.15: 31,  2014.12.26: 60,  2014.12.30: 95}

让这些2合并为一个对象:

var combined = {};
for(var key in v){
    combined[key] = { date: key, visits: v[key], docs: 0 };
}
for(var key in d){
    combined[key] = combined[key] || { date: key, visits: 0 };
    combined[key].docs = d[key];
}

现在,combined是一个包含数据的非常好的对象:

{
  "2014.12.25": { date: "2014.12.25", visits: 141, docs: 0 },
  "2014.12.26": { date: "2014.12.26", visits: 630, docs: 60 },
  "2014.12.30": { date: "2014.12.30", visits: 71,  docs: 95 },
  "2014.12.15": { date: "2014.12.15", visits: 0,   docs: 31 }
}

但是,由于您需要一组对象,我们将不得不再次迭代:

var result = [];
for(var key in combined){
    result.push(combined[key]);
}

结果:

[
  { date: "2014.12.25", visits: 141, docs: 0 },
  { date: "2014.12.26", visits: 630, docs: 60 },
  { date: "2014.12.30", visits: 71,  docs: 95 },
  { date: "2014.12.15", visits: 0,   docs: 31 }
]

当然,这不是获得所需结果的最短或最佳方式,但我希望它能让您了解此过程中涉及的步骤。

答案 1 :(得分:0)

您所要做的就是循环数据。

var visitors =  [ { '2014.12.25': 141 }, { '2014.12.26': 630 }, { '2014.12.30': 71 } ];
var documents = [ { '2014.12.15': 31 }, { '2014.12.26': 60, }, { '2014.12.30': 95  } ];
var data = {};
visitors.forEach(function(el){var k = Object.keys(el)[0]; data[k] = data[k] || {}; data[k].visits = el[k];});
documents.forEach(function(el){var k = Object.keys(el)[0]; data[k] = data[k] || {}; data[k].docs = el[k];});
for(prop in data){
    if(data[prop].docs === void 0){data[prop].docs = 0};
    if(data[prop].visits === void 0){data[prop].visits = 0};
}

这会以组合的方式提供您的数据,您只需添加逻辑以将日期从键移动到属性。

答案 2 :(得分:0)

使用下划线组合数组的另一种方法:

var visitors =  [ { '2014.12.25': 141 }, { '2014.12.26': 630 }, { '2014.12.30': 71 } ];
var documents = [ { '2014.12.15': 31 }, { '2014.12.26': 60, }, { '2014.12.30': 95  } ];

var visits = new Array();
var docs = new Array();

for (i=0; i < visitors.length; i++) {
    for (key in visitors[i])    {    
        visits.push({"date": key, "visits": visitors[i][key], "docs":0});
    }
}

for (i=0; i < documents.length; i++) {
    for (key in documents[i])    {
        docs.push({"date": key,"docs": documents[i][key]});
    }
}

mergeByProperty(visits, docs, 'date');

function mergeByProperty(visits, docs, prop) {
    _.each(docs, function(arr2obj) {
        var arr1obj = _.find(visits, function(arr1obj) {
            return arr1obj[prop] === arr2obj[prop];
        });

        //If the object already exist extend it with the new values from arr2, otherwise just add the new object to arr1
        arr1obj ? _.extend(arr1obj, arr2obj) : visits.push(arr2obj);
    });
}

console.log(visits);