【问题标题】:Find in an array of objects duplicate set values在对象数组中查找重复的集合值
【发布时间】:2018-09-11 13:27:48
【问题描述】:

我有一个带有 HTML 表格的 UI,我们可以在其中添加动态行和列 (angularjs)

该表有 2 个静态列 ID 和描述,其余列是动态列,用户必须添加一列或多列。(单击按钮) 单击“保存”按钮,我想验证用户是否添加了唯一的动态列。

Below Variable 保存如下行的数组:

 $scope.myTable.Rows 

以下是用户仅添加 1 个动态列和 2 行时生成的数组。这里 id & description 是静态列,而“0”是添加的动态列。

{0: "1111", description: "desc1", id: "1111"}
{0: "2222", description: "desc2", id: "2222"}

另外一个当3个动态列,3行添加的例子:

{0: "a1", 1: "a2", 2: "a3", description: "desc1", id: "1111"}
{0: "a5", 1: "a6", 2: "a7", description: "desc2", id: "2222"}
{0: "a9", 1: "a10", 2: "a11", description: "desc3", id: "3333"}

我想检查上面的数组是否只有动态列的组合是唯一的。即根据上述数组设置的动态列0、1、2的值不应在数组的任何其他行中重复。

所以下面的数组集不应该通过验证:

{0: "a1", 1: "a2", 2: "a3", description: "desc1", id: "1111"}
{0: "a5", 1: "a6", 2: "a7", description: "desc2", id: "2222"}
{0: "a1", 1: "a2", 2: "a3", description: "desc3", id: "3333"}

如您所见,上面的第 3 行与第 1 行相似。我不想考虑列“id”和“description”

虽然下面仍然是独一无二的:

{0: "a1", 1: "a2", 2: "a3", description: "desc1", id: "1111"}
{0: "a5", 1: "a6", 2: "a7", description: "desc2", id: "2222"}
{0: "a1", 1: "a2", 2: "a9", description: "desc3", id: "3333"}

我曾尝试在以下位置查看几个帖子: How can I check if the array of objects have duplicate property values?

但其中大部分是查看单个属性并查看是否存在重复但不是在组合集合中。

我希望我已经清楚地解释了我的要求。如果您需要更多信息,请告诉我。

--更新--

我已经尝试过:

 let array = [
  {0: "a1", 1: "a2", 2: "a3", description: "desc1", id: "1111"},
 {0: "a5", 1: "a6", 2: "a7", description: "desc2", id: "2222"},
 {0: "a1", 1: "a2", 2: "a3", description: "desc3", id: "3333"}];

 let jsonRows = JSON.parse(JSON.stringify(array));
 var valueArr = jsonRows.map(function(item){ return item."0" });
   //above gives error: Uncaught SyntaxError: Unexpected string
 var isDuplicate = valueArr.some(function(item, idx){ 
return valueArr.indexOf(item) != idx 
 });

console.log(jsonRows);

【问题讨论】:

  • 您可以发布您已经尝试过的任何作品吗,拜托...
  • 如果你想使用库,那么 lodash 可以帮助你。交集和联合的例子有很多数组函数。
  • @Niraj 我也正要推荐 lodash,但我认为 _.uniqBy 会是更好的使用方法。
  • @Lex _.uniqBy 是 lodash 提供的方法。
  • @Niraj 正确。

标签: javascript arrays angularjs


【解决方案1】:

这是我认为我们可以在这里做的非常简单的事情,创建一个map,其中key作为每一行的每个动态属性的值。如果已经找到属性存在重复项,则获取每一行并添加到地图。

我使用|| 作为分隔符将每个值组合成一个唯一键,使用一个不会成为动态属性值的唯一键。

 function isUniqueData(data) {
    let map = {}, isUnique = true;
    data.filter(function(item, index) {
      let prop = "";
      for(var key in item) {
        if(key != "description" && key != "id") {
          prop += item[key] + "||";
        }  
      }
      if(map[prop]) {
        isUnique = false;
      } else {
        map[prop] = item;
      }
    }); 
    return isUnique;
 }

var data1 = [
  {0: "a1", 1: "a2", 2: "a3", description: "desc1", id: "1111"},
  {0: "a5", 1: "a6", 2: "a7", description: "desc2", id: "2222"},
  {0: "a5", 1: "a6", 2: "a7", description: "desc2", id: "2222"},
  {0: "a1", 1: "a2", 2: "a9", description: "desc3", id: "3333"}
];
console.log(isUniqueData(data1))

var data2 = [
  {0: "a1", 1: "a2", description: "desc1", id: "1111"},
  {0: "a5", 1: "a6", description: "desc2", id: "2222"},
  {0: "a1", 1: "a4", description: "desc3", id: "3333"}
];
console.log(isUniqueData(data2))

【讨论】:

    【解决方案2】:

    解释你的问题:

    给定多个键,如何在数组中找到键:值对多次出现的所有行?

    我使用了这些行:

    var rows = [
      {0: 'a1', 1: 'a2', 2: 'a3', description: 'desc1', id: '1111'},
      {0: 'a5', 1: 'a6', 2: 'a7', description: 'desc2', id: '2222'},
      {0: 'a1', 1: 'a2', 2: 'a3', description: 'desc3', id: '3333'}
    ];
    

    我的回答可能有点啰嗦:

    1. 针对我希望唯一的单独键列表递归遍历数组。
    2. 对于每个给定的键,找出该键的每个值的出现次数。
    3. 如果值的计数是> 1,则将该行推送到重复数组中

    您可以使用 Lodash 中的 #countBy 等函数来缩短解决方案。

    function duplicates(arr, keys = []) {
      if (keys.length) {
        const key = keys[0];
        const keyValueCounts = count(arr.map(row => row[key]));
    
        return duplicates(
          arr.reduce((acc, row) => {
            if (keyValueCounts[row[key]] > 1) {
              return acc.concat(row);
            } else {
              return acc;
            }
          }, []),
          keys.slice(1)
        );
      } else {
        return arr;
      }
    }
    
    /// or _.countsBy(arr);
    function count(arr) {
      const counts = {};
    
      arr.forEach(value => {
        counts[value] = Number.isInteger(counts[value])
          ? counts[value] + 1
          : 1;
      });
    
      return counts;
    }
    
    console.log(duplicates(rows, [0, 1, 2]));
    

    【讨论】:

      【解决方案3】:

      您可以编写一个查看所有元素的函数,直到找到两个具有相同的012 属性:

      let testData = [{0: "a1", 1: "a2", 2: "a3", description: "desc1", id: "1111"},{0: "a5", 1: "a6", 2: "a7", description: "desc2", id: "2222"},{0: "a1", 1: "a2", 2: "a3", description: "desc3", id: "3333"}]
      
      
      function areElementsUnique(arr) {
        if (arr.length === 1) return true; // no need to check if there is only one element
        for (el of arr) {
          if (arr.filter(elm => (el[0] === elm[0] && el[1] === elm[1] && el[2] === elm[2])).length > 1)
            return false
        };
        return true;
      }
      
      console.log(areElementsUnique(testData));

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-04-17
        • 1970-01-01
        • 2021-11-14
        • 2018-08-13
        • 1970-01-01
        • 2014-12-27
        相关资源
        最近更新 更多