Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 按唯一键组合对象数组_Javascript_Arrays_Underscore.js - Fatal编程技术网

Javascript 按唯一键组合对象数组

Javascript 按唯一键组合对象数组,javascript,arrays,underscore.js,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 } ]; 每个数组中的日期可能不同。 如何将数组转换为以下结构(即按日期键组合):

我有两个对象数组。其中一个每天有访客计数,另一个每天有文档计数。像这样:

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  } ];
每个数组中的日期可能不同。 如何将数组转换为以下结构(即按日期键组合):

允许使用的工具:
JavaScript
Undescore.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  } ];
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};
}

这将以组合方式提供数据,您所要做的就是添加逻辑,将日期从键移动到属性。

让我们在native 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}
让我们将这两个对象合并为一个对象:

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 }
]

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

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

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);
var访问者=[{'2014.12.25':141},{'2014.12.26':630},{'2014.12.30':71}];
var文件=[{'2014.12.15':31},{'2014.12.26':60,},{'2014.12.30':95}];
var=newarray();
var docs=新数组();
对于(i=0;i
当然,我已经尝试了很多方法,我的代码现在有超过2页的篇幅来解决这个问题,但我怀疑我走的方向是否正确。我相信社区可能知道有一个巧妙的解决方案。是的,这应该只是几个(少于10个)代码行…不想冒犯,但如果你有两页的代码来解决一个问题,那么这个问题就被完全忽略了。@Sukima如果我知道更好的解决方案,我就不会寻求帮助了。无论是谁写了这个作业,都会把原始对象搞砸。你究竟为什么要制作一个以日期为键的对象数组-@Cerburs
void 0
是完全有效的用法,我不明白你的观点是什么。当然,这是有效的,但这是一种偏执的用法,对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  } ];

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);