组合对象数组 ({a:a,b:b, c:c},{a:a,d:d,c:c}) 到 ({a:a,b:c,d:c })
Combining object arrays ({a:a,b:b, c:c},{a:a,d:d,c:c}) to ({a:a,b:c,d:c})
我有一个数据列表,我需要转换这些数据,"pivot" 将一列转换为多列。
我拥有的对象列表如下所示:
var list = [
{
"date": "2016-05-31",
"action": "test",
"value": 10
},
{
"date": "2016-05-31",
"action": "run",
"value": 8
},
{
"date": "2016-06-01",
"action": "delete",
"value" : 2
},
{
"date": "2016-06-01",
"action": "test",
"value": 5
},
]
我需要将其转换为图表库,使其看起来像这样:
var list = [
{
"date": "2016-05-31",
"test": 10,
"run": 8,
"delete": 0
},
{
"date": "2016-06-01",
"test": 5,
"run": 0,
"delete": 2
}
]
是否有使用 underscore.js 函数(例如 _.groupBy 和 _.map 等)的相当简单的方法...?
这会迭代两次以创建日期映射,然后再次迭代以插入缺失的属性?
var list = [{
"date": "2016-05-31",
"action": "test",
"value": 10
}, {
"date": "2016-05-31",
"action": "run",
"value": 8
}, {
"date": "2016-06-01",
"action": "delete",
"value": 2
}, {
"date": "2016-06-01",
"action": "test",
"value": 5
}];
var map = {};
list.forEach(function(o) {
if ( !(o.date in map) ) map[o.date] = {};
map[o.date][o.action] = o.value;
});
var sorted_list = Object.keys(map).map(function(k) {
return {
"date" : k,
"test" : (map[k].test || 0),
"run" : (map[k].run || 0),
"delete" : (map[k].delete || 0)
}
});
document.body.innerHTML = '<pre>' + JSON.stringify(sorted_list, 0, 4) + '</pre>';
这是一种方法,使用 .reduce()
创建一个临时对象来累积值,然后 .map()
创建最终数组:
var temp = list.reduce(function(c, v) {
(c[v.date] || (c[v.date]={}))[v.action] = v.value;
return c;
}, {});
var output = Object.keys(temp).map(function(k) {
return {
date : k,
test : temp[k].test || 0,
run : temp[k].run || 0,
"delete" : temp[k].delete || 0
}
});
这是一个ES6解决方案,它没有硬编码test
、run
或delete
,而是首先检索数据中所有可能的动作:
function pivot(list) {
var actions = list.reduce( (actions, o) => (actions[o.action] = 0, actions), {} );
var res = list.reduce( (res, o) => ((res[o.date] = res[o.date] || Object.assign({ date: o.date }, actions))[o.action] += o.value, res), {});
return Object.keys(res).map(key => res[key]);
}
// Sample data
var list = [{
"date": "2016-05-31",
"action": "test",
"value": 10
}, {
"date": "2016-05-31",
"action": "run",
"value": 8
}, {
"date": "2016-06-01",
"action": "delete",
"value": 2
}, {
"date": "2016-06-01",
"action": "test",
"value": 5
}];
// Call
var res = pivot(list);
// Output
console.log(res);
如果在同一日期重复操作值,则将相应的值加在一起(因此假定数值)。
另类专注于速度
根据对速度的评论,我在这里介绍一个在一个循环中完成工作的函数:
var list = [{
"date": "2016-05-31",
"action": "test",
"value": 10
}, {
"date": "2016-05-31",
"action": "run",
"value": 8
}, {
"date": "2016-06-01",
"action": "delete",
"value": 2
}, {
"date": "2016-06-01",
"action": "test",
"value": 5
}];
function pivot(list) {
var res = {}, arr = [];
for (var o of list)
(res[o.date] || (arr[arr.push(res[o.date] = {
date: o.date,
test: 0,
run : 0,
"delete": 0
})-1]))[o.action] += o.value;
return arr;
}
var res = pivot(list);
console.log(res);
我已将此添加到 the test suit Ismail RBOUH 创建。
这是一个下划线解决方案:
var result = _.chain(list).groupBy("date")
.mapObject(function(item, key) {
var d = {date: key};
for(var i in item) d[item[i].action] = item[i].value;
return d;
}).values().value();
var list = [{
"date": "2016-05-31",
"action": "test",
"value": 10
}, {
"date": "2016-05-31",
"action": "run",
"value": 8
}, {
"date": "2016-06-01",
"action": "delete",
"value": 2
}, {
"date": "2016-06-01",
"action": "test",
"value": 5
}, ];
var result = _.chain(list).groupBy("date")
.mapObject(function(item, key) {
var d = {date: key};
for(var i in item) d[item[i].action] = item[i].value;
return d;
}).values().value();
console.log(result);
<script src="
https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
我有一个数据列表,我需要转换这些数据,"pivot" 将一列转换为多列。
我拥有的对象列表如下所示:
var list = [
{
"date": "2016-05-31",
"action": "test",
"value": 10
},
{
"date": "2016-05-31",
"action": "run",
"value": 8
},
{
"date": "2016-06-01",
"action": "delete",
"value" : 2
},
{
"date": "2016-06-01",
"action": "test",
"value": 5
},
]
我需要将其转换为图表库,使其看起来像这样:
var list = [
{
"date": "2016-05-31",
"test": 10,
"run": 8,
"delete": 0
},
{
"date": "2016-06-01",
"test": 5,
"run": 0,
"delete": 2
}
]
是否有使用 underscore.js 函数(例如 _.groupBy 和 _.map 等)的相当简单的方法...?
这会迭代两次以创建日期映射,然后再次迭代以插入缺失的属性?
var list = [{
"date": "2016-05-31",
"action": "test",
"value": 10
}, {
"date": "2016-05-31",
"action": "run",
"value": 8
}, {
"date": "2016-06-01",
"action": "delete",
"value": 2
}, {
"date": "2016-06-01",
"action": "test",
"value": 5
}];
var map = {};
list.forEach(function(o) {
if ( !(o.date in map) ) map[o.date] = {};
map[o.date][o.action] = o.value;
});
var sorted_list = Object.keys(map).map(function(k) {
return {
"date" : k,
"test" : (map[k].test || 0),
"run" : (map[k].run || 0),
"delete" : (map[k].delete || 0)
}
});
document.body.innerHTML = '<pre>' + JSON.stringify(sorted_list, 0, 4) + '</pre>';
这是一种方法,使用 .reduce()
创建一个临时对象来累积值,然后 .map()
创建最终数组:
var temp = list.reduce(function(c, v) {
(c[v.date] || (c[v.date]={}))[v.action] = v.value;
return c;
}, {});
var output = Object.keys(temp).map(function(k) {
return {
date : k,
test : temp[k].test || 0,
run : temp[k].run || 0,
"delete" : temp[k].delete || 0
}
});
这是一个ES6解决方案,它没有硬编码test
、run
或delete
,而是首先检索数据中所有可能的动作:
function pivot(list) {
var actions = list.reduce( (actions, o) => (actions[o.action] = 0, actions), {} );
var res = list.reduce( (res, o) => ((res[o.date] = res[o.date] || Object.assign({ date: o.date }, actions))[o.action] += o.value, res), {});
return Object.keys(res).map(key => res[key]);
}
// Sample data
var list = [{
"date": "2016-05-31",
"action": "test",
"value": 10
}, {
"date": "2016-05-31",
"action": "run",
"value": 8
}, {
"date": "2016-06-01",
"action": "delete",
"value": 2
}, {
"date": "2016-06-01",
"action": "test",
"value": 5
}];
// Call
var res = pivot(list);
// Output
console.log(res);
如果在同一日期重复操作值,则将相应的值加在一起(因此假定数值)。
另类专注于速度
根据对速度的评论,我在这里介绍一个在一个循环中完成工作的函数:
var list = [{
"date": "2016-05-31",
"action": "test",
"value": 10
}, {
"date": "2016-05-31",
"action": "run",
"value": 8
}, {
"date": "2016-06-01",
"action": "delete",
"value": 2
}, {
"date": "2016-06-01",
"action": "test",
"value": 5
}];
function pivot(list) {
var res = {}, arr = [];
for (var o of list)
(res[o.date] || (arr[arr.push(res[o.date] = {
date: o.date,
test: 0,
run : 0,
"delete": 0
})-1]))[o.action] += o.value;
return arr;
}
var res = pivot(list);
console.log(res);
我已将此添加到 the test suit Ismail RBOUH 创建。
这是一个下划线解决方案:
var result = _.chain(list).groupBy("date")
.mapObject(function(item, key) {
var d = {date: key};
for(var i in item) d[item[i].action] = item[i].value;
return d;
}).values().value();
var list = [{
"date": "2016-05-31",
"action": "test",
"value": 10
}, {
"date": "2016-05-31",
"action": "run",
"value": 8
}, {
"date": "2016-06-01",
"action": "delete",
"value": 2
}, {
"date": "2016-06-01",
"action": "test",
"value": 5
}, ];
var result = _.chain(list).groupBy("date")
.mapObject(function(item, key) {
var d = {date: key};
for(var i in item) d[item[i].action] = item[i].value;
return d;
}).values().value();
console.log(result);
<script src="
https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>