我有两个这样的对象:
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}]}
)
我想要一个相同格式的对象,但是:
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}]}
)
我以这种方式使用了Lodash的mergeWith
:
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个问题:
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}]
}
答案 0 :(得分:0)
您可以在 ES6 中通过Array.reduce
,Object.entries
和Array.forEach
进行操作:
Note in the example I have extra objects in "first" array for tesitng purposes
const o1 = {first: [{timestamp: "2018-12-09T16:00:00.000", count: 3},{timestamp: "2019-12-09T16:00:00.000", count: 1}], second: [{timestamp: "2018-12-09T17:00:00.000", count: 2}], third: [{timestamp: "2018-12-09T18:00:00.000", count: 2}]}
const o2 = {first: [{timestamp: "2018-12-09T16:00:00.000", count: 0}, {timestamp: "2019-12-09T16:00:00.000", count: 11}], second: [{timestamp: "2018-12-09T17:00:00.000", count: 0}], third: [{timestamp: "2018-12-09T18:00:00.000", count: 3}]}
const groupObjects = arr => arr.reduce((r,c) => {
Object.entries(c).forEach(([k,v]) => {
let key = `${k}`
r[key] = r[key] || []
v.forEach(({timestamp, count}, i) => {
r[key][i] = r[key][i] || ({timestamp: new Date(timestamp), count: 0})
r[key][i].count += count
})
})
return r
}, {})
console.log(groupObjects([o1, o2]))
唯一棘手的事情是,您需要对对象键first
进行分组,然后对每个对象执行第二次操作以获取总和。
这是假设object1
和object2
始终具有相同的数组长度。
答案 1 :(得分:0)
所以mergeWith所执行的操作是递归地应用定制器,所以您要检查的是类型,例如typeof(a) == 'string'
,如果对象中将有另一种类型的字符串数据,则必须添加更复杂的逻辑,以确保您使用正则表达式合并具有正确日期格式的字符串。
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}]}
function mergeData(a,b){
return _.mergeWith(a,b, (a,b)=>{
if(typeof(a) == "string") return new Date(a);
if(typeof(a) == "number") return a+b;
});
}
console.log(mergeData(object1, object2));
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.11/lodash.min.js"></script>
答案 2 :(得分:0)
从可读性的角度来看,将其分解为较小的问题可能更容易。例如,您需要能够在日期上合并子数组,还需要为每个对象中的不同键集做好准备。
这解决了每个问题:
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)
答案 3 :(得分:0)
Lodash的_.mergeWith()
回调将键作为第三个参数。您可以使用它来决定如何合并项目:
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 mergefn = (...args) =>
_.mergeWith({}, ...args, (o, s, k) => {
if(_.eq(k, 'timestamp')) return new Date(s);
if(_.eq(k, 'count')) return (o || 0) + s;
});
const result = mergefn(object1, object2);
console.log(result);
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.11/lodash.min.js"></script>