【问题标题】:How can I see if Object Array has element in Another Object Array?如何查看对象数组是否在另一个对象数组中有元素?
【发布时间】:2022-09-27 16:21:04
【问题描述】:

有没有办法判断一个对象数组是否与另一个对象数组有任何公共元素,以及该对象相交是什么? (如 Contains 函数)。在下面的示例中,对象数组 1 中的 ProductId3 也包含在对象数组 2 中。

我正在考虑使用双 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
}
]
  • 你的问题有点太笼统了。你有没有真正面临的问题?您的问题有很多“有效”的答案。不要预先优化。
  • 我们正在对我们的 web ui 验证进行重复检查 cc @RuanMendes 我编写了一个解决方案,但是检查是否有更优化/高效/速记的方法,谢谢
  • 我们正在检查所有对象成员 cc @RuanMendes
  • 我有一些问题:问题 1.集合之一是静态的(不会改变吗?)?如果两者都是动态的,那么除了两个嵌套循环复杂度 O(N*M) 之外,我看不到其他方法。这些的实现可能会因代码风格而异。问题2这些数组的预期是什么?

标签: javascript typescript


【解决方案1】:

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

  1. 将每个数组转换为一个新数组,其元素是原始子数组值的 JSON 表示。这是执行两次的 o(N) 操作。
  2. 在新的、已转换的数组中找到最短的。将另一个转换为集合。这也是o(N)。
  3. 对于较短的转换数组的每个元素,检查集合是否包含该值。这也是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]);
        }
    }

【讨论】:

    【解决方案2】:

    您可以通过查找来实现这一点只要具有相同的对象产品编号通过filter & some 在一行代码中的组合。

    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)
    

    【讨论】:

    • 顺便说一句,我们正在搜索所有属性成员,而不仅仅是 productId
    • 为什么这背后的逻辑是什么?因为您为 ProductId 3 提供的产品的示例数据对于两个数组具有相同的元素!
    • 有时它们会有所不同,我无法控制数据,谢谢
    • 好的,作为上述方法,您可以为要比较的所有元素添加&amp;&amp; o1.ProductName=== o2.ProductName &&...
    【解决方案3】:

    如果您想要深度相等比较(对于嵌套对象或所有 (key, value) 对),我建议使用更好的方法,即使用 base64 编码/解码来提高比较性能。 所以我的方法是:

    1. 合并数组并将对象转换为 base64 字符串。
    2. 将重复组合在一起
    3. 过滤重复项
    4. 将 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));

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-09-07
      • 1970-01-01
      • 2016-04-24
      • 2017-09-17
      • 2021-12-26
      • 1970-01-01
      • 1970-01-01
      • 2019-06-05
      相关资源
      最近更新 更多