javascript - 合并缺少键的对象
问题描述
我有两个这样的对象:
const object1 = {first: [{timestamp: "2018-12-09T16:00:00.000", count: 3}], second: [{timestamp: "2018-12-09T17:00:00.000", count: 2}], third: [{timestamp: "2018-12-09T18:00:00.000", count: 2}]}
const object2 = {first: [{timestamp: "2018-12-09T16:00:00.000", count: 0}], second: [{timestamp: "2018-12-09T17:00:00.000", count: 0}], third: [{timestamp: "2018-12-09T18:00:00.000", count: 3}]}
(object1
并且object2
可能有长度 > 1 的数组,例如:
const object1 = {first: [{timestamp: "2018-12-09T16:00:00.000", count: 3}, {timestamp: "2018-12-09T16:30:00.000", count: 5}], second: [{timestamp: "2018-12-09T17:00:00.000", count: 2}], third: [{timestamp: "2018-12-09T18:00:00.000", count: 2}]}
const object2 = {first: [{timestamp: "2018-12-09T16:00:00.000", count: 0}, {timestamp: "2018-12-09T16:30:00.000", count: 0}], second: [{timestamp: "2018-12-09T17:00:00.000", count: 0}], third: [{timestamp: "2018-12-09T18:00:00.000", count: 3}]}
)
我想要一个相同格式的对象,但是:
- key 的值
timestamp
应该是真实数据而不是字符串(所以我需要这样做new Data(timestamp)
) - 键的值
count
应该是总和
所以预期的结果是:
const res = {first: [{timestamp: 2018-12-09T16:00:00.000, count: 3}], second: [{timestamp: 2018-12-09T17:00:00.000, count: 2}], third: [{timestamp: 2018-12-09T18:00:00.000, count: 5}]}
(如果object1
并且object2
数组的长度> 1:
const res = {first: [{timestamp: 2018-12-09T16:00:00.000, count: 3}, {timestamp: "2018-12-09T16:30:00.000", count: 5}], second: [{timestamp: 2018-12-09T17:00:00.000, count: 2}], third: [{timestamp: 2018-12-09T18:00:00.000, count: 5}]}
)
我mergeWith
以这种方式使用了 Lodash:
const merged = _.mergeWith(object1, object2, (objValue, srcValue) => [
{ count: objValue[0].count + srcValue[0].count },
])
const r = Object.entries(merged).map(([key, value], i) => {
return { number: key, timestamp: value.map(convertTimestamp) }
})
console.log('r: ', r)
哪里convertTimestamp
是:
const convertTimestamp = (d) => ({
...d,
timestamp: new Date(d.timestamp),
})
这是结果:
[
{
"number": "first",
"timestamp": [
{
"count": 3,
"timestamp": null
}
]
},
{
"number": "second",
"timestamp": [
{
"count": 2,
"timestamp": null
}
]
},
{
"number": "third",
"timestamp": [
{
"count": 5,
"timestamp": null
}
]
}
]
显然它不起作用。它有3个问题:
- 没有正确值的嵌套对象
- 时间戳不正确
- if
object1
和object2
具有相同的密钥,但如果它们是:
const object1 = {first: [{timestamp: "2018-12-09T16:00:00.000", count: 3}], second: [{timestamp: "2018-12-09T17:00:00.000", count: 2}], third: [{timestamp: "2018-12-09T18:00:00.000", count: 2}]}
const object2 = {second: [{timestamp: "2018-12-09T17:00:00.000", count: 0}], third: [{timestamp: "2018-12-09T18:00:00.000", count: 3}]}
(缺少object2 first
),该程序不起作用...
我需要帮助
这是一个可测试的代码:
function mergeData(object1, object2) {
const merged = _.mergeWith(object1, object2, (objValue, srcValue) => [
{ count: objValue[0].count + srcValue[0].count},
])
const r = Object.entries(merged).map(([key, value], i) => {
return { number: key, timestamp: value.map(convertTimestamp) }
})
return r
}
const convertTimestamp = (d) => {
return ({
...d,
timestamp: new Date(d.timestamp),
})
}
const object1 = {first: [{timestamp: "2018-12-09T16:00:00.000", count: 3}], second: [{timestamp: "2018-12-09T17:00:00.000", count: 2}], third: [{timestamp: "2018-12-09T18:00:00.000", count: 2}]}
const object2 = {first: [{timestamp: "2018-12-09T16:00:00.000", count: 0}], second: [{timestamp: "2018-12-09T17:00:00.000", count: 0}], third: [{timestamp: "2018-12-09T18:00:00.000", count: 3}]}
const result = mergeData(object1, object2)
console.log(result)
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.11/lodash.min.js"></script>
一些例子:
// example 1
const object1 = {
first: [{timestamp: "2018-12-09T16:00:00.000", count: 3}, {timestamp: "2018-12-09T16:30:00.000", count: 5}],
second: [{timestamp: "2018-12-09T17:00:00.000", count: 2}],
third: [{timestamp: "2018-12-09T18:00:00.000", count: 2}]
}
const object2 = {
first: [{timestamp: "2018-12-09T16:00:00.000", count: 0}, {timestamp: "2018-12-09T16:30:00.000", count: 0}],
second: [{timestamp: "2018-12-09T17:00:00.000", count: 0}],
third: [{timestamp: "2018-12-09T18:00:00.000", count: 3}]
}
const result = {
first: [{timestamp: "2018-12-09T16:00:00.000", count: 3}, {timestamp: "2018-12-09T16:30:00.000", count: 5}],
second: [{timestamp: "2018-12-09T17:00:00.000", count: 2}],
third: [{timestamp: "2018-12-09T18:00:00.000", count: 5}]
}
// example 2
const object1 = {
first: [{timestamp: "2018-12-09T16:00:00.000", count: 3}, {timestamp: "2018-12-09T16:30:00.000", count: 5}],
second: [{timestamp: "2018-12-09T17:00:00.000", count: 2}],
third: [{timestamp: "2018-12-09T18:00:00.000", count: 2}]
}
const object2 = {
first: [{timestamp: "2018-12-09T16:00:00.000", count: 0}],
second: [{timestamp: "2018-12-09T17:00:00.000", count: 0}],
third: [{timestamp: "2018-12-09T18:00:00.000", count: 3}]
}
const result = {
first: [{timestamp: "2018-12-09T16:00:00.000", count: 3}, {timestamp: "2018-12-09T16:30:00.000", count: 5}],
second: [{timestamp: "2018-12-09T17:00:00.000", count: 2}],
third: [{timestamp: "2018-12-09T18:00:00.000", count: 5}]
}
// example 3
const object1 = {
first: [{timestamp: "2018-12-09T16:00:00.000", count: 3}, {timestamp: "2018-12-09T16:30:00.000", count: 5}],
second: [{timestamp: "2018-12-09T17:00:00.000", count: 2}],
third: [{timestamp: "2018-12-09T18:00:00.000", count: 2}]
}
const object2 = {
second: [{timestamp: "2018-12-09T17:00:00.000", count: 0}],
third: [{timestamp: "2018-12-09T18:00:00.000", count: 3}]
}
const result = {
first: [{timestamp: "2018-12-09T16:00:00.000", count: 3}, {timestamp: "2018-12-09T16:30:00.000", count: 5}],
second: [{timestamp: "2018-12-09T17:00:00.000", count: 2}],
third: [{timestamp: "2018-12-09T18:00:00.000", count: 5}]
}
// example 4
const object1 = {
first: [{timestamp: "2018-12-09T16:00:00.000", count: 3}, {timestamp: "2018-12-09T16:30:00.000", count: 5}],
second: [{timestamp: "2018-12-09T17:00:00.000", count: 2}, {timestamp: "2018-12-09T17:30:00.000", count: 20}, {timestamp: "2018-12-09T18:00:00.000", count: 10}],
third: [{timestamp: "2018-12-09T18:00:00.000", count: 2}]
}
const object2 = {
first: [{timestamp: "2018-12-09T16:00:00.000", count: 0}, {timestamp: "2018-12-09T16:30:00.000", count: 0}],
second: [{timestamp: "2018-12-09T17:00:00.000", count: 0}, {timestamp: "2018-12-09T17:30:00.000", count: 6}, {timestamp: "2018-12-09T18:00:00.000", count: 2}],
third: [{timestamp: "2018-12-09T18:00:00.000", count: 3}]
}
const result = {
first: [{timestamp: "2018-12-09T16:00:00.000", count: 3}, {timestamp: "2018-12-09T16:30:00.000", count: 5}],
second: [{timestamp: "2018-12-09T17:00:00.000", count: 2}, {timestamp: "2018-12-09T17:30:00.000", count: 26}, {timestamp: "2018-12-09T18:00:00.000", count: 12}],
third: [{timestamp: "2018-12-09T18:00:00.000", count: 5}]
}
解决方案
从可读性的角度来看,将其分解为更小的问题可能更容易。例如,您需要能够在日期上合并子数组,并且您还需要为每个对象中的不同键集做好准备。
这解决了每一个问题:
const object1 = {first: [{timestamp: "2018-12-09T16:00:00.000", count: 3}], second: [{timestamp: "2018-12-09T17:00:00.000", count: 2}], third: [{timestamp: "2018-12-09T18:00:00.000", count: 2}]}
const object2 = {first: [{timestamp: "2018-12-09T16:00:00.000", count: 0}], second: [{timestamp: "2018-12-09T17:00:00.000", count: 0}], third: [{timestamp: "2018-12-09T18:00:00.000", count: 3}]}
// a function to merge arrays with defaulf values
// in case one is not defined
function mergeArray(a1 =[], a2 =[]){
let hash = [...a1, ...a2].reduce((hash, {timestamp, count}) =>{
if(!hash.hasOwnProperty(timestamp)) hash[timestamp] = {timestamp, count:0}
hash[timestamp].count += count
return hash
}, {})
return Object.values(hash)
}
// a set of all keys between the tow objects
// so the objects don't nees to have the same keys
// we'll loop over this to make sure we get everything
const allKeys = new Set([...Object.keys(object1), ...Object.keys(object2)])
// now for each known key merge the arrays
let res = {}
for (key of allKeys){
res[key] = mergeArray(object1[key], object2[key])
}
console.log(res)
推荐阅读
- android - Jetpack Compose - 立柱 - 重心
- laravel - 只有一个刀片而不是 12 个
- javascript - 如何从 JavaScript 中的 JSON 树获取嵌套的父路径?
- c++ - 如何将 OpenMP 和 MPI 导入大型 CLion CMake 项目?
- snowflake-cloud-data-platform - 如何在 SnowFlake 中加入 query_id 和 METADATA$ROW_ID
- python-3.x - 有什么方法可以找到多个图像的边界并单独裁剪它们?
- r - 从一系列网页中解析图表
- python - 将原始 CFA 缓冲区保存到原始图像
- javascript - 阿波罗客户端在反应原生的初始重新加载中返回未定义
- javascript - 如何使用私有方法正确配置 ES6 类的 eslint?