根据多个唯一值过滤

时间:2021-03-10 19:00:33

标签: javascript arrays object filter

我正在尝试确定以下最佳方法。

我有两个数组,如下所示:

const a = [
{
  Employee: "00001",
  Seq: "01",
  ReportDate: "2021-03-10T00:00:00.000",
  ReportName: "test report",
},
{
  Employee: "00002",
  Seq: "01",
  ReportDate: "2020-03-10T00:00:00.000",
  ReportName: "test report 2",
},
];


const b = [
{
  Employee: "00001",
  EmplName: "William Apple",
  ReportDate: "2021-03-10T00:00:00.000",
  ReportName: "test report",
  Posted: "Y",
  Seq: "01",
},
{
  Employee: "00003",
  EmplName: "John Smith",
  ReportDate: "2021-03-10T00:00:00.000",
  ReportName: "test report 3",
  Posted: "Y",
  Seq: "01",
},
];

我想过滤掉数组“b”中的任何内容,它不包含数组“a”中的一个对象中的所有 4 个确切值。

所以,根据上面的例子,我会留下:

// from array 'b'
const c = [
{
  Employee: "00001",
  EmplName: "William Apple",
  ReportDate: "2021-03-10T00:00:00.000",
  ReportName: "test report",
  Posted: "Y",
  Seq: "01",
}
];

我已经研究了各种方法来做到这一点。我不能只检查对象是否相等,因为数组 'a' 将只包含 4 个值/键,而数组 'b' 将包含更多/动态数量。

通过循环和多个 IF 语句使用 Filter 方法是最好的方法吗?

3 个答案:

答案 0 :(得分:2)

您可以使用 .reduce 迭代 a 的项目并将它们存储在 Map 中,其中 Employeekey 和其他属性(Seq , ReportDate, ReportName) 是 value

之后,使用 .filter 获取来自 b 的项目,其中它们的 Employee 存在于地图中并且其他三个属性匹配。

const a = [
  { Employee: "00001", Seq: "01", ReportDate: "2021-03-10T00:00:00.000", ReportName: "test report" },
  { Employee: "00002", Seq: "01", ReportDate: "2020-03-10T00:00:00.000", ReportName: "test report 2" }
];
const b = [
  { Employee: "00001", EmplName: "William Apple", ReportDate: "2021-03-10T00:00:00.000", ReportName: "test report", Posted: "Y", Seq: "01" },
  { Employee: "00003", EmplName: "John Smith", ReportDate: "2021-03-10T00:00:00.000", ReportName: "test report 3", Posted: "Y", Seq: "01" }
];

const employeesMap = a.reduce((map,employee) => {
  const { Employee, ...attributes } = employee;
  map.set(Employee, attributes);
  return map;
}, new Map);

const res = b.filter(employee => {
  const { Employee, Seq, ReportDate, ReportName } = employee;
  const employeeFromA = employeesMap.get(Employee);
  return employeeFromA && 
    employeeFromA.Seq === Seq && 
    employeeFromA.ReportDate === ReportDate && 
    employeeFromA.ReportName === ReportName;
});

console.log(res);

答案 1 :(得分:2)

我会像这样从循环代码中分离出精确对象匹配的测试:

const subObject = (a, b) => 
  Object .entries (a) .every (([k, v]) => b [k] == v)

const matches = (xs, ys) => 
  ys .filter (y => xs .some (x => subObject (x, y)))

const a = [{Employee: "00001", Seq: "01", ReportDate: "2021-03-10T00:00:00.000", ReportName: "test report"}, {Employee: "00002", Seq: "01", ReportDate: "2020-03-10T00:00:00.000", ReportName: "test report 2"}]
const b = [{Employee: "00001", EmplName: "William Apple", ReportDate: "2021-03-10T00:00:00.000", ReportName: "test report", Posted: "Y", Seq: "01"}, {Employee: "00003", EmplName: "John Smith", ReportDate: "2021-03-10T00:00:00.000", ReportName: "test report 3", Posted: "Y", Seq: "01"}]

console .log (matches (a, b))

subObject 检查 a 的每个属性在 b 中是否具有相同的值。

matches 使用它根据第一个列表是否包含作为其子对象的某个元素来过滤第二个列表。

两者都是非常简单的函数。虽然我们可以将 subObject 内联到 matches 中,但我认为它本身很有用,并且可以生成更好的代码。

答案 2 :(得分:1)

const results = b.filter(bv => !!a.find(av => Object.keys(av).filter(ak => av[ak] === bv[ak]).length === Object.keys(av).length));

console.log(results);

这会将“b”数组过滤到仅那些在“a”中也有匹配项的元素。 “匹配”在这里由“a”项中的所有键/值与“b”项中的所有相应键/值匹配来确定。 “b”项中的无关键将被忽略。