获取两个数组之间的精确匹配元素

时间:2019-10-27 13:44:46

标签: javascript arrays typescript

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

array1 = [
         {id:1, children: ['a', 'b']},
         {id:2, children: ['a', 'b']},
         {id:3, children: ['b', 'c']},
         {id:4, children: ['c', 'a']},
         {id:5, children: ['a', 'b', 'c']}];

array2 = ['a', 'b'];

现在,我想在JS / TS中编写代码,该代码将找到array1的确切对象,其中array 2的子数组的每个元素与array 1的子数组的每个元素完全匹配(顺序无关紧要)。

我尝试使用三个过滤器来解决此问题,这些过滤器还具有数组1和array2之间的子数组长度匹配的附加条件。但是,如果至少有一个元素与那些具有所需数组长度的子数组相匹配,这也会起作用。

如果有人给我解决方案,我将非常感谢。

array1
.filter(a => a.children
.filter(b => array2
.filter(c => b === c)).length === array2.length);

编辑:

在上面的示例中,我实际上将问题简化了一些。在我的实际项目中,这两个数组如下:

 const productOrders: ProductOrder[] =
      [
        {
          productId: 1, subProductOrders:
            [{subProduct: {subProductId: 1}}, {subProduct: 
{subProductId: 2}}]
        },
        {
          productId: 1, subProductOrders:
            [{subProduct: {subProductId: 2}}, {subProduct: 
{subProductId: 1}}]
        },
        {
          productId: 1, subProductOrders:
            [{subProduct: {subProductId: 2}}, {subProduct: 
{subProductId: 3}}]
        },
        {
          productId: 1, subProductOrders:
            [{subProduct: {subProductId: 1}}, {subProduct: 
{subProductId: 2}}, {subProduct: {subProductId: 3}}]
        },
      ];

    const matchingCriteria: SubProductOrder[] =
      [
        [{subProduct: {subProductId: 1}}, {subProduct: {subProductId: 
2}}]

      ];

现在,我想从productOrders数组中找到产品,其中subProductOrders数组的subProductId与matchingCriteria数组的subProductId匹配(顺序无关紧要)。在上面的示例中,尽管subProductsIds无序,但productOrders数组的前两个产品应该匹配

4 个答案:

答案 0 :(得分:4)

您可以使用Set并对照此结构检查孩子。

var array1 = [{ id: 1, children: ['a', 'b'] }, { id: 2, children: ['a', 'b'] }, { id: 3, children: ['b', 'c'] }, { id: 4, children: ['c', 'a'] },  { id: 5, children: ['a', 'b', 'c'] }],
    array2 = ['a', 'b'],
    set2 = new Set(array2),
    result = array1.filter(({ children }) =>
        children.length === set2.size && children.every(Set.prototype.has, set2));

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

对于更复杂的数据结构,您可以解构所需的部分并对照一组subProductId进行检查。

const
    getId = ({ subProduct: { subProductId } }) => subProductId;

var productOrders = [{ productId: 1, subProductOrders: [{ subProduct: { subProductId: 1 } }, { subProduct: { subProductId: 2 } }] }, { productId: 1, subProductOrders: [{ subProduct: { subProductId: 2 } }, { subProduct: { subProductId: 1 } }] }, { productId: 1, subProductOrders: [{ subProduct: { subProductId: 2 } }, { subProduct: { subProductId: 3 } }] }, { productId: 1, subProductOrders: [{ subProduct: { subProductId: 1 } }, { subProduct: { subProductId: 2 } }, { subProduct: { subProductId: 3 } }] }],
    matchingCriteria = [{ subProduct: { subProductId: 1 } }, { subProduct: { subProductId: 2 } }],
    set2 = new Set(matchingCriteria.map(getId)),
    result = productOrders.filter(({ subProductOrders }) =>
        subProductOrders.length === set2.size &&
        subProductOrders.every(o => set2.has(getId(o)))
    );

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

答案 1 :(得分:1)

您可以在单个过滤器中使用Array#every()和长度

const arr1 = [
   {id:1, children: ['a', 'b']},
   {id:2, children: ['a', 'b']},
   {id:3, children: ['b', 'c']},
   {id:4, children: ['c', 'a']},
   {id:5, children: ['a', 'b', 'c']}
];


const arr2 = ['a', 'b'];

const matched = arr1.filter(({children: c}) => c.length === arr2.length && arr2.every(v => c.includes(v)))

console.log(matched)

答案 2 :(得分:0)

array1 = [
         {id:1, children: ['a', 'b']},
         {id:2, children: ['b', 'a']},
         {id:3, children: ['b', 'c']},
         {id:4, children: ['c', 'a']},
         {id:5, children: ['a', 'b', 'c']}];

array2 = ['a', 'b'];

const x = array1
  .map(a => a.children.sort())
  .filter(a => a.length === array2.length)
  .map(a => a.sort())
  .filter(a => JSON.stringify(a)==JSON.stringify(array2))

console.log(x)

答案 3 :(得分:-1)

您正在根据element.children与array2的相等性过滤array1元素。 因此,我鼓励您看一下这些answers。因为它讨论了javascript中两个数组的相等性。

并根据您的需要修改以下代码,这只是最简单的选项之一:

array1.filter((element,index) => {
      return JSON.stringify(element.children) === JSON.stringify(array2)
})