javascript - 合并 javascript 对象

标签 javascript merge 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];
        }
    }
}

本质上,这枚举了源的所有属性。如果该属性是对象的自己属性(也就是说,它不是从原型(prototype)继承的属性),我们会将该属性复制到目标。

现在,为了对您想要执行的操作类型进行建模,我们可以将其分解为更简单的操作:给定一个现有数组,将另一个对象放入该数组中,必要时进行合并。一个简单的实现可能如下所示:

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 还没有真正拥有真正的“哈希表”。我们拥有的最接近的东西是对象,它只能有字符串键。这对我们有用,但我们确实需要谨慎:无论好坏,浏览器 vendor 创建了一些具有特殊意义的属性名称,例如 __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)。无论如何,您还可以修改其中的 for 循环以循环数组数组,然后循环这些数组中的对象,这就是我的高尔夫版本所做的。与高尔夫版本的另一个区别是高尔夫版本避免修改原始数组或对象,这将是对未混淆版本的相对简单的修改:要制作副本,只需合并到一个空对象中。

希望事情能够解决。

关于javascript - 合并 javascript 对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32217485/

相关文章:

python - 两个表之间的非标准交互以避免非常大的合并

javascript-objects - 对象文字中的 Javascript 怪异嵌套赋值问题

javascript - IE8 背景大小不工作

javascript - 如何比较 JavaScript 表格中的单元格并测试是否相等? indexOf 是如何工作的?

javascript - ajax 调用成功后,jQuery 重新绑定(bind) $(window).scroll()

javascript - Highchart 中的线条着色需要很长时间

sql - Oracle SQL - 匹配时更新并插入

java - Hibernate:在 StackOverflowError 中合并多对多结果

javascript - 是否可以通过循环数组来填充对象实例?

javascript - call() 和 apply() 实际上做了什么来欺骗方法来处理类似数组的对象