如何查看对象数组中是否有另一个对象数组中的元素?

vjhs03f7  于 2022-10-02  发布在  Java
关注(0)|答案(7)|浏览(311)

有没有一种方法可以判断一个对象数组是否有与另一个对象数组相同的元素,以及该对象的交集是什么?(如CONTAINS函数)。在下面的示例中,对象数组1中的ProductId3也包含在对象数组2中。

我在考虑使用Double for循环。然而,有没有一种更有效/更优的方法,或者是简写的ECMA或Lodash函数?

array1.forEach(arr1 => {
  array2.forEach(arr2 => { 
       if (arr1.productId === arr2.productId && 
           arr1.productName === arr2.productName ...

检查所有对象成员,而不仅仅是ProductID

对象数组1:

[
{
    ProductId: 50,
    ProductName: 'Test1',
    Location: 77,
    Supplier: 11,
    Quantity: 33
},
{
    ProductId: 3,
    ProductName: 'GHI',
    Location: 1,
    Supplier: 4,
    Quantity: 25
}
]

对象数组2:

[
{
    ProductId: 1,
    ProductName: 'ABC',
    Location: 3,
    Supplier: 4,
    Quantity: 52
},
{
    ProductId: 2,
    ProductName: 'DEF',
    Location: 1,
    Supplier: 2,
    Quantity: 87
},
{
    ProductId: 3,
    ProductName: 'GHI',
    Location: 1,
    Supplier: 4,
    Quantity: 25
},
{
    ProductId: 4,
    ProductName: 'XYZ',
    Location:  5,
    Supplier: 6,
    Quantity: 17
}
]

资源:

How to determine if Javascript array contains an object with an attribute that equals a given value?

Javascript: Using .includes to find if an array of objects contains a specific object

dzhpxtsq

dzhpxtsq1#

  • 有没有办法判断一个对象数组和另一个对象数组有没有公共元素?*-可以,可以通过Array.some()方法来实现。如果在数组中找到所提供的函数返回TRUE的元素,则返回TRUE;否则返回FALSE。
const array1 = [{
  ProductId: 50,
  ProductName: 'Test1',
  Location: 77,
  Supplier: 11,
  Quantity: 33
}, {
  ProductId: 3,
  ProductName: 'GHI',
  Location: 1,
  Supplier: 4,
  Quantity: 25
}];

const array2 = [{
  ProductId: 1,
  ProductName: 'ABC',
  Location: 3,
  Supplier: 4,
  Quantity: 52
}, {
  ProductId: 2,
  ProductName: 'DEF',
  Location: 1,
  Supplier: 2,
  Quantity: 87
}, {
  ProductId: 3,
  ProductName: 'GHI',
  Location: 1,
  Supplier: 4,
  Quantity: 25
}, {
  ProductId: 4,
  ProductName: 'XYZ',
  Location:  5,
  Supplier: 6,
  Quantity: 17
}];

const isCommonProducts = array2.some(({ ProductId }) => array1.map(obj => obj.ProductId).includes(ProductId));

console.log(isCommonProducts);
  • 更新:*根据作者的评论,我们必须检查对象的所有属性。因此,我们可以通过将对象转换为字符串来比较JSON字符串来实现这一点。

现场演示:

const array1 = [{
  ProductId: 50,
  ProductName: 'Test1',
  Location: 77,
  Supplier: 11,
  Quantity: 33
}, {
  ProductId: 3,
  ProductName: 'GHI',
  Location: 1,
  Supplier: 4,
  Quantity: 25
}];

const array2 = [{
  ProductId: 1,
  ProductName: 'ABC',
  Location: 3,
  Supplier: 4,
  Quantity: 52
}, {
  ProductId: 2,
  ProductName: 'DEF',
  Location: 1,
  Supplier: 2,
  Quantity: 87
}, {
  ProductId: 3,
  ProductName: 'GHI',
  Location: 1,
  Supplier: 4,
  Quantity: 25
}, {
  ProductId: 4,
  ProductName: 'XYZ',
  Location:  5,
  Supplier: 6,
  Quantity: 17
}];

const getFilteredProducts = array2.filter(productObj => JSON.stringify(array1).indexOf(JSON.stringify(productObj)) !== -1);

console.log(getFilteredProducts);
xghobddn

xghobddn2#

如果我们可以假设每个数组的元素(我们将它们称为子词典)以相同的顺序包含完全相同的键,那么我的想法是:

1.将每个数组转换为一个新数组,该数组的元素是原始子词典值的JSON表示。这是一个执行了两次的o(N)操作。
1.在转换后的新数组中,找到最短的数组。将另一个转换为集合。这也是o(N)。
1.对于较短的转换数组的每个元素,检查集合是否包含此值。这也是o(N)。

let arr1 = [
{
    ProductId: 50,
    ProductName: 'Test1',
    Location: 77,
    Supplier: 11,
    Quantity: 33
},
{
    ProductId: 3,
    ProductName: 'GHI',
    Location: 1,
    Supplier: 4,
    Quantity: 25
}
];

let arr2 = [
{
    ProductId: 1,
    ProductName: 'ABC',
    Location: 3,
    Supplier: 4,
    Quantity: 52
},
{
    ProductId: 2,
    ProductName: 'DEF',
    Location: 1,
    Supplier: 2,
    Quantity: 87
},
{
    ProductId: 3,
    ProductName: 'GHI',
    Location: 1,
    Supplier: 4,
    Quantity: 25
},
{
    ProductId: 4,
    ProductName: 'XYZ',
    Location:  5,
    Supplier: 6,
    Quantity: 17
}
];

// Convert each sub-array's values to JSON string:
let arr1New = arr1.map(function(arr) {return JSON.stringify(Object.values(arr));});
let arr2New = arr2.map(function(arr) {return JSON.stringify(Object.values(arr));});

// Find shortest array of JSON strings:
const l1 = arr1New.length;
const l2 = arr2New.length;
// enumerate shortest list
let list, set, l, arr;
if (l1 <= l2) {
    list = arr1New;
    set = new Set(arr2New);
    l = l1;
    arr = arr1;
}
else {
    list = arr2New;
    set = new Set(arr1New);
    l = l2;
    arr = arr2;
}

for(let i = 0; i < l; i++) {
    if (set.has(list[i])) {
        console.log(arr[i]);
    }
}

更新

如果子词典关键字不一定是有序的,那么我们必须从这些关键字有序的地方创建新的子词典:

// Create function to create new dictionaries sorted by keys

function sort_dict(d) {
    items = Object.keys(d).map(function(key) {
        return [key, d[key]];
    });
    items.sort(function(first, second) {
        return first[0] < second[0] ? -1 : (first[0] > second[0] ? 1 : 0);
    });
    sorted_dict = {};
    items.forEach(function(x) {
        sorted_dict[x[0]] = x[1];
    });
    return(sorted_dict);
}

// And then we have these modified lines:
// Convert each sub-array's values to JSON string:
let arr1New = arr1.map(function(arr) {return JSON.stringify(Object.values(sort_dict(arr)));});
let arr2New = arr2.map(function(arr) {return JSON.stringify(Object.values(sort_dict(arr)));});

修改代码

let arr1 = [
{
    ProductId: 50,
    ProductName: 'Test1',
    Location: 77,
    Supplier: 11,
    Quantity: 33
},
{
    ProductName: 'GHI',
    Location: 1,
    Supplier: 4,
    Quantity: 25,
    ProductId: 3 // Not in the same order as the others
}
];

let arr2 = [
{
    ProductId: 1,
    ProductName: 'ABC',
    Location: 3,
    Supplier: 4,
    Quantity: 52
},
{
    ProductId: 2,
    ProductName: 'DEF',
    Location: 1,
    Supplier: 2,
    Quantity: 87
},
{
    ProductId: 3,
    ProductName: 'GHI',
    Location: 1,
    Supplier: 4,
    Quantity: 25
},
{
    ProductId: 4,
    ProductName: 'XYZ',
    Location:  5,
    Supplier: 6,
    Quantity: 17
}
];

function sort_dict(d) {
    items = Object.keys(d).map(function(key) {
        return [key, d[key]];
    });
    items.sort(function(first, second) {
        return first[0] < second[0] ? -1 : (first[0] > second[0] ? 1 : 0);
    });
    sorted_dict = {};
    items.forEach(function(x) {
        sorted_dict[x[0]] = x[1];
    });
    return(sorted_dict);
}

// Convert each sub-array's values to JSON string:
let arr1New = arr1.map(function(arr) {return JSON.stringify(Object.values(sort_dict(arr)));});
let arr2New = arr2.map(function(arr) {return JSON.stringify(Object.values(sort_dict(arr)));});

// Find shortest array of JSON strings:
const l1 = arr1New.length;
const l2 = arr2New.length;
// enumerate shortest list
let list, set, l, arr;
if (l1 <= l2) {
    list = arr1New;
    set = new Set(arr2New);
    l = l1;
    arr = arr1;
}
else {
    list = arr2New;
    set = new Set(arr1New);
    l = l2;
    arr = arr2;
}

for(let i = 0; i < l; i++) {
    if (set.has(list[i])) {
        console.log(arr[i]);
    }
}
pkwftd7m

pkwftd7m3#

您可以通过在一行代码中组合filtersome找到具有相同ProductID的**对象来实现这一点。

const arr1 = [
{
    ProductId: 50,
    ProductName: 'Test1',
    Location: 77,
    Supplier: 11,
    Quantity: 33
},
{
    ProductId: 3,
    ProductName: 'GHI',
    Location: 1,
    Supplier: 4,
    Quantity: 25
}
]

const arr2 = [
{
    ProductId: 1,
    ProductName: 'ABC',
    Location: 3,
    Supplier: 4,
    Quantity: 52
},
{
    ProductId: 2,
    ProductName: 'DEF',
    Location: 1,
    Supplier: 2,
    Quantity: 87
},
{
    ProductId: 3,
    ProductName: 'GHI',
    Location: 1,
    Supplier: 4,
    Quantity: 25
},
{
    ProductId: 4,
    ProductName: 'XYZ',
    Location:  5,
    Supplier: 6,
    Quantity: 17
}
]

const similarObjects= arr1.filter(o1 => arr2.some(o2 => o1.ProductId === o2.ProductId));
console.log(similarObjects)

为了更多的理解!这是同一作品的长篇形式:

const similarObjects= arr1.filter(function (o1) {
    return arr2.some(function (o2) {
        return o1.ProductId === o2.ProductId; // return the ones with equal ProductId
   });
});

console.log(similarObjects)
hrysbysz

hrysbysz4#

如果您希望进行深度相等比较(针对嵌套对象或所有(key, value)对),我建议使用base64编码/解码来提高比较性能。因此,我的方法是:

1.合并数组并将对象转换为Base64字符串。
1.将递归组合在一起
1.过滤重复项
1.将Base64字符串还原为其原始对象。

const convertObjToBase64 = o => btoa(JSON.stringify(o));
const convertBase64ToObj = str => JSON.parse(atob(str));
const arrayToObjCount = arr => arr.reduce((res, v) => {
  res[v] = (res[v] ?? 0) + 1;
  return res;
}, {});

const findDuplicateObjectsInMultipleArrays = (...arrays) => {
  const base64Array = Array.from(arrays.flat(), convertObjToBase64);
  const objCount = arrayToObjCount(base64Array);
  const duplicates = Object.entries(objCount).reduce((prev, [k, v]) => {
    if (v > 1) {
      prev.push(convertBase64ToObj(k));
    }
    return prev;
  }, []);
  return duplicates;
}

let arr1 = [{
    ProductId: 50,
    ProductName: 'Test1',
    Location: {
      LocationId: 77,
      LocationName: 'Location 77'
    },
    Supplier: 11,
    Quantity: 33
  },
  {
    ProductId: 3,
    ProductName: 'GHI',
    Location: {
      LocationId: 1,
      LocationName: 'Location 1'
    },
    Supplier: 4,
    Quantity: 25
  }
];

let arr2 = [{
    ProductId: 1,
    ProductName: 'ABC',
    Location: {
      LocationId: 3,
      LocationName: 'Location 3'
    },
    Supplier: 4,
    Quantity: 52
  },
  {
    ProductId: 2,
    ProductName: 'DEF',
    Location: {
      LocationId: 1,
      LocationName: 'Location 1'
    },
    Supplier: 2,
    Quantity: 87
  },
  {
    ProductId: 3,
    ProductName: 'GHI',
    Location: {
      LocationId: 1,
      LocationName: 'Location 1'
    },
    Supplier: 4,
    Quantity: 25
  },
  {
    ProductId: 4,
    ProductName: 'XYZ',
    Location: {
      LocationId: 5,
      LocationName: 'Location 5'
    },
    Supplier: 6,
    Quantity: 17
  }
];

let arr3 =[ 
  {
    ProductId: 2,
    ProductName: 'DEF',
    Location: {
      LocationId: 1,
      LocationName: 'Location 1'
    },
    Supplier: 2,
    Quantity: 87
  },
  {
    ProductId: 3,
    ProductName: 'GHI',
    Location: {
      LocationId: 2,
      LocationName: 'Location 2'
    },
    Supplier: 4,
    Quantity: 25
  },
   {
    ProductId: 4,
    ProductName: 'XYZ',
    Location: {
      LocationId: 6,
      LocationName: 'Location 5'
    },
    Supplier: 6,
    Quantity: 17
  }
];
console.log(findDuplicateObjectsInMultipleArrays(arr1, arr2, arr3));
qltillow

qltillow5#

我将发布两个解决方案:

第一个解决方案是可读性的代码不是100%的性能优化,但它是可读性和优雅的。

带有工作代码的操场链接

首先,我们需要一个比较任意类型的两个对象的方法。该方法比较第一级属性,因此如果我们有嵌套的对象属性,它将通过引用比较它们。

const areTheSame = (a: any, b: any) => {
  const objAProps = Object.keys(a).filter(key => typeof a[key] !== "function")
  const objBProps = Object.keys(b).filter(key => typeof b[key] !== "function")

  if (objAProps.length !== objBProps.length) {
    return false;
  }

  return objAProps.every((propName) => a[propName] === b[propName]);
}

然后,我们可以实现适用于任何数组类型的可读性INTERSECT方法:

const getIntersection = (array1: Array<any>, array2: Array<any>) => {
  return array1.filter(a1Item => array2.some(a2Item => areTheSame(a1Item, a2Item)));
}

第二种解决方案以性能为导向,缺点是可读性不太好

首先,我们计算所有对象的Has,然后在单个forEach循环中,我们可以基于该Hash识别交集。我使用了MD5,但可以使用任何散列算法或库。

她的是stack blitz link playground。它可以运行,忽略导入错误。

const getArrayIntersection = (
  firstArray: Array<any>,
  secondArray: Array<any>
) => {
  const array1Hashed = firstArray.map((i) => md5(JSON.stringify(i)));
  const array2Set = new Set(secondArray.map((i) => md5(JSON.stringify(i))));

  const result: Array<any> = [];

  array1Hashed.forEach((itemHash, index) => {
    if (array2Set.has(itemHash)) {
      result.push(firstArray[index]);
    }
  });
  return result;
};
fivyi3re

fivyi3re6#

对于简单但相当快的解决方案,您可以(1)使用第一个阵列中的Set,然后(2)filter基于第一个阵列中的ID的第二个阵列,这样您只需在每个阵列中检查一次O(n)

let arr1 = [
  {
    ProductId: 50,
    ProductName: "Test1",
    Location: 77,
    Supplier: 11,
    Quantity: 33,
  },
  {
    ProductId: 3,
    ProductName: "GHI",
    Location: 1,
    Supplier: 4,
    Quantity: 25,
  },
];

let arr2 = [
  {
    ProductId: 1,
    ProductName: "ABC",
    Location: 3,
    Supplier: 4,
    Quantity: 52,
  },
  {
    ProductId: 2,
    ProductName: "DEF",
    Location: 1,
    Supplier: 2,
    Quantity: 87,
  },
  {
    ProductId: 3,
    ProductName: "GHI",
    Location: 1,
    Supplier: 4,
    Quantity: 25,
  },
  {
    ProductId: 4,
    ProductName: "XYZ",
    Location: 5,
    Supplier: 6,
    Quantity: 17,
  },
];

const getCommonItems = (arr1, arr2) => {
  let firstIdSet = new Set(arr1.map((product) => product.ProductId)); //1
  return arr2.filter((product) => firstIdSet.has(product.ProductId)); //2
};

console.log(getCommonItems(arr1, arr2));
egdjgwm8

egdjgwm87#

只需携带@Roh?t Jíndal,您可以检查数组是否有一个特定的对象,如下所示:

const resultObj = arr1.filter(obj => obj.id=== "whatever" && obj.productname == "whatever") // ETC ETC

相关问题