[英]Merging javascript objects
希望合並兩個對象。 但是,當兩個對象中都存在具有相同值的屬性“ date”時,其他屬性(tag1和tag2)將合並在同一日期下。
輸入示例
var myVar1 = [
{
"date": "2015-07-16",
"tag1": 35.34},
{
"date": "2015-07-18",
"tag1": 34.12}
];
var myVar2 = [
{
"date": "2015-07-16",
"tag2": 45.34},
{
"date": "2015-07-17",
"tag2": 44.12}
];
所需的輸出
mergedVar = [
{
"date": "2015-07-16",
"tag1": 35.34,
"tag2": 45.34},
{
"date": "2015-07-17",
"tag2": 44.12},
{
"date": "2015-07-18",
"tag1": 34.12}
];
我發表評論的想法是,其他人會發表更嚴肅的答案,但是由於沒有人來,我想我將描述您可能會認真做的事情。
首先,您必須知道如何將一個對象合並到另一個對象中。 不太困難,但是您必須知道如何使用for
- in
,這是不常講授的,通常最好包括一個hasOwnProperty
檢查,該檢查甚至更不常用:
function mergeObjectInto(source, target) {
for(var property in source) {
if(Object.prototype.hasOwnProperty.call(source, property)) {
target[property] = source[property];
}
}
}
本質上,這枚舉了源的所有屬性。 如果該屬性是對象本身的屬性(也就是說,它不是從其原型繼承而來的),則可以將該屬性復制到目標中。
現在,要對您要執行的操作進行建模,我們可以將其分解為一個更簡單的操作:給定一個現有數組,將另一個對象放入該數組,並在必要時合並。 天真的實現可能看起來像這樣:
function mergeObjectIntoArray(existingArray, newObject) {
// Search for an already-existing object in the array that shares the same
// value for the `date' property.
var correspondingExistingObject = null;
for(var index = 0, length = existingArray.length; index < length; index++) {
if(existingArray[index].date === newObject.date) {
correspondingExistingObject = existingArray[index];
break;
}
}
if(correspondingExistingObject !== null) {
// If we found an existing object that corresponds to our new object, just
// merge any new properties in rather than adding a new item to the array.
mergeObjectInto(newObject, correspondingExistingObject);
}else{
// Otherwise, bite the bullet and add the new object since there's nothing
// we can usefully merge into.
existingArray.push(newObject);
}
}
然后,您可以通過循環調用此函數來實現所需的合並操作。 但是,如果計算出來的話,那將是二次時間,如果必須處理大量數據項,這將是一個問題。 碰巧的是,有一種方法可以解決它。 如果我們將項目分類為一個由date
屬性作為鍵的類似哈希表的結構,則可以在固定時間內檢查是否有一個帶有該日期的對象,如果是,則將其合並; 否則,添加它。 這導致整個算法的線性時間非常合理。
一個問題是,直到最近使用ECMAScript 6,JavaScript才真正擁有真正的“哈希表”。 我們擁有的最接近的東西是對象,只能有字符串鍵。 這對我們有用,但我們需要謹慎行事:無論好壞,瀏覽器供應商都創建了一些具有特殊意義的屬性名稱,例如__proto__
,我們確實不想繼續使用,因此我們將在我們的鍵之前添加一些字符,以防止與內置名稱發生任何沖突。 為此,我選擇了#
。 ( #
是一個哈希,它是一個哈希表。)
在代碼中,這是如何實現的,這一次該函數接收整個項目數組並將所有具有重復date
屬性值的對象合並:
function mergeDuplicateObjectsInArray(array) {
var result = [];
var objectsByDate = {};
for(var index = 0, length = array.length; index < length; index++) {
var object = array[index];
var hashKey = '#' + object.date;
var mergeTarget;
if(Object.prototype.hasOwnProperty.call(objectsByDate, hashKey)) {
// Already have an object by that date; we ought to merge into that.
mergeObjectInto(object, objectsByDate[object.date]);
}else{
// No object by that date yet; we'll be the first.
result.push(object);
objectsByDate[object.date] = object;
}
}
return result;
}
這仍然遺漏了最后一件事:它只是將對象合並在單個數組中,而不是兩個不同的數組。 但是,如果您使用兩個數組的對象創建單個數組,例如myVar1.concat(myVar2)
, myVar1.concat(myVar2)
。 無論如何,您還可以修改其中的for
循環以遍歷數組數組,然后遍歷那些數組中的對象,這就是我的高爾夫球版本所做的。 高爾夫球版本的另一個區別是高爾夫球版本避免修改原始數組或對象,這是對未混淆版本的相對簡單的修改:要進行復制,只需合並到一個空對象中即可。
希望這可以清除一切。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.