根据外部对象属性删除对象数组中的元素

3

我有一个对象,我想从其中一个属性的对象数组中删除元素,这个属性是基于外部对象匹配属性的。

这里使用npm deep-diff来比较两个对象。

我的问题在于combineDuplicateRecords函数会将每个记录与每个记录进行比较,导致identities数组中出现重复项。因此,identities最终会变成:

[{
    id: "111",
    identities: [
      {
        id: "111"
      },
      {
        id: "111"
      },
      {
        id: "222"
      },
      {
        id: "222"
      },
      {
        id: "333"
      },
      {
        id: "333"
      }
    ]
}]

当我真正想要它看起来像这样时:

[{
id: "111",
identities:[
      {
        id: "222"
      },
      {
        id: "333"
      }
    ]
}]

代码:

var requestRecords = [
      {
        vid: "12345",
        id: "12345",
        email: "gft@test.com",
        firstName: "GrandFathering",
        lastName: "TestMN",
        postalCode: "55443-2410",
        phone: "123-456-7890",
        key: "1212"
      },
      {
        vid: "121212",
        id: "12222",
        email: "g233@test.com",
        firstName: "NoMatch",
        lastName: "NoMatchFound",
        postalCode: "43233-2410",
        phone: "123-456-7890",
        key: "121233"
      },
      {
        vid: "111",
        id: "111",
        email: "ffffft@test.com",
        firstName: "samebatch",
        lastName: "samebatch",
        postalCode: "5545",
        phone: "123-456-7890",
        key: "3333",
      },
      {
        vid: "222",
        id: "222",
        email: "ffffft@test.com",
        firstName: "samebatch",
        lastName: "samebatch",
        postalCode: "5545",
        phone: "123-456-7890",
        key: "4444",
      },
      {
        vid: "333",
        id: "333",
        email: "ffffft@test.com",
        firstName: "samebatch",
        lastName: "samebatch",
        postalCode: "5545",
        phone: "123-456-7890",
        key: "55",

      }
    ];


  combineDuplicateRecords = (arrayOfRecords, prefilter) => {
    const recordsToRemove = [];
    arrayOfRecords.forEach(firstRecord => {
      arrayOfRecords.forEach((secondRecord, index) => {
        if (
          firstRecord.firstName == secondRecord.firstName &&
          firstRecord.lastName == secondRecord.lastName &&
          firstRecord.dateOfBirth == secondRecord.dateOfBirth &&
          firstRecord.phone == secondRecord.phone &&
          firstRecord.postalCode == secondRecord.postalCode &&
          firstRecord.id !=
            secondRecord.id
        ) {
          const identities = [];
          let identity = {};
          this.preserveExisitingIdentities(secondRecord, identities);
          this.preserveExisitingIdentities(firstRecord, identities);
          identity = this.setIdentityDifferencesBetweenRecords(
            firstRecord,
            secondRecord,
            prefilter,
            identity
          );
          identities.push(identity);
          firstRecord["identities"] = identities;
          recordsToRemove.push(index);
        }
      });
    });

    [...new Set(recordsToRemove)].forEach(index => {
      arrayOfRecords.splice(index, 1);
    });
    return arrayOfRecords;
  };

    preserveExisitingIdentities = (record, identities) => {
    if (record.hasOwnProperty("identities")) {
      record.identities.forEach(identity => {
        identities.push(identity);
      });
    }
    return identities;
  };

    setIdentityDifferencesBetweenRecords = (
    firstIdentity,
    secondIdentity,
    prefilter,
    identity
  ) => {
    const differences = Diff(firstIdentity, secondIdentity, prefilter);
    let i = differences.length;
    while (i--) {
      if (differences[i].path[0] == "vid") {
        differences.splice(i, 1);
      }

      if (differences[i].path[0] == "identities") {
        differences.splice(i, 1);
      }
      //we only want to keep the differences so we remove kind D
      if (differences[i]?.kind == "D") {
        differences.splice(i, 1);
      }
    }
    differences.forEach(diff => {
      identity[diff.path[0]] = diff.lhs;
    });
    return identity;
  };
  console.log(JSON.stringify(combineDuplicateRecords(requestRecords)));

看起来你已经做了很多现有的工作。最简单的方法是通过一个小算法,基于内部键删除那些重复的内容,而不需要进行任何代码修改。你需要帮忙写吗? - Andrew
如果有更好的方法并且放弃我的初始想法是一个更好的选择,那就太好了。 - Josh Adams
1个回答

1
抓取每个内部id并将它们保存在数据结构中,然后使用Array#find查找整个对象并将其插入回identities

const array = [
{
    id: "111",
    identities: [
        {
            id: "111"
        },
        {
            id: "111"
        },
        {
            id: "222"
        },
        {
            id: "222"
        },
        {
            id: "333"
        },
        {
            id: "333"
        }
    ]
}
]

const cleanObject = (obj) => {
const allIds = obj.identities.map(({ id }) => id)
const mainId = obj.id
const uniqueIds = new Set(allIds)
uniqueIds.delete(mainId)

const nextIdentities = [...uniqueIds].map(currId => {
    return obj.identities.find(({ id }) => currId === id)
})
obj.identities = nextIdentities
return obj
};

const el = array.map(entry => {
return cleanObject(entry)
})

console.log(el)


我认为id:111不应该在内部数组中。 - Josh Adams
在你的第一段代码片段中,那不是有效的JavaScript代码,所以我做出了一些(错误的)假设来确定其结构。你能否整理一下并显示给我们确切的代码是什么? - Andrew
@JoshAdams 我对数据结构的假设是正确的,但我对预期输出的解释实际上是错误的(哎呀)。已更新。 - Andrew

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接