获取具有唯一值的数组的长度

时间:2018-07-10 11:27:20

标签: javascript arrays

所以我有一个包含一些对象的数组。我想将这些对象相互比较。如果fromId AND 属性相同,则表示重复。

示例:

toId
const data = [{
  fromId: 1,
  toId: 2,
  finished: true
}, {
  fromId: 1,
  toId: 2,
  finished: false
}, {
  fromId: 5,
  toId: 9,
  finished: false
}, {
  fromId: 1,
  toId: 5,
  finished: true
}, {
  fromId: 2,
  toId: 1,
  finished: false
}];

$(document).ready(() => {
  const duplicates = data.filter(x =>
    data
    .filter(y => y.fromId == x.fromId && y.toId == x.toId)
    .length > 1
  );

  console.log(duplicates);
});

我想获取此数据数组的长度,但只能使用唯一值。我试图删除所有重复的值并在此处找到解决方案

  

Get all non-unique values (i.e.: duplicate/more than one occurrence) in an array

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
const data = [1, 2, 3, 4, 5, 2, 2, 6, 7, 8, 2, 9, 2, 2, 2, 2, 2];

$(document).ready(() => {
  const uniqueValues = data.filter((connection, index) => data.indexOf(connection) == index);

  console.log(uniqueValues);
});

但是在此解决方案中,我仅对整个对象使用<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>。如何比较indexOffromId并删除相同匹配项中的重复项?

我将从原始数组中删除一个

toId

因为{ fromId: 1, toId: 2, finished: false } fromId已经存在于另一个对象中。

6 个答案:

答案 0 :(得分:2)

不是将filter嵌套在另一个filter中(糟糕的运行时复杂度),因为您只是在寻找唯一数组的长度,因此可以将每个fromId和将toId放入字符串中,然后将该字符串放入Set(仅保留唯一值)中,然后检查Set的大小:

const data=[{fromId:1,toId:2,finished:!0},{fromId:1,toId:2,finished:!1},{fromId:5,toId:9,finished:!1},{fromId:1,toId:5,finished:!0},{fromId:2,toId:1,finished:!1}];

const idSet = new Set(data.map(({ fromId, toId }) => fromId + '_' + toId));
console.log(idSet.size);

答案 1 :(得分:2)

您可以使用Order来过滤具有唯一对象的数组,然后将长度值与唯一数组一起获取:

Array.reduce()
const data = [{
  fromId: 1,
  toId: 2,
  finished: true
}, {
  fromId: 1,
  toId: 2,
  finished: false
}, {
  fromId: 5,
  toId: 9,
  finished: false
}, {
  fromId: 1,
  toId: 5,
  finished: true
}, {
  fromId: 2,
  toId: 1,
  finished: false
}];

$(document).ready(() => {
  var uniqueArray = data.reduce((acc, obj)=>{
    var existObj = acc.find(item => item.fromId === obj.fromId && item.toId === obj.toId);
    if(existObj){
      return acc;
    }
    acc.push(obj);
    return acc;
  },[]);
console.log('unique array ', uniqueArray);
console.log('length of unique object ', uniqueArray.length);
});

答案 2 :(得分:0)

您可以创建一个新数组,并仅推送元素一次,使用jQuery中的 inArray 函数检查它们是否已经存在:

const data = [{
  fromId: 1,
  toId: 2,
  finished: true
}, {
  fromId: 1,
  toId: 2,
  finished: false
}, {
  fromId: 5,
  toId: 9,
  finished: false
}, {
  fromId: 1,
  toId: 5,
  finished: true
}, {
  fromId: 2,
  toId: 1,
  finished: false
}];

$(document).ready(() => {
   
  var filtered = [];
  $.each(data, function(i, item){
      if($.inArray(item, filtered) === -1){
        filtered.push(item);
      }
      
      
  });
  console.log(filtered.length);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

jQuery inArray()

答案 3 :(得分:0)

虽然对您的情况来说,SecretPerformance的答案可能更好,但是不比较项目标识的indexOf替代方案是findIndex。但是,这仅是ES6 +,但是大多数现代浏览器都实现了它(对不起,没有IE11)。

来源: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/findIndex

答案 4 :(得分:0)

可以使用简单的forEach-这是纯JS,而不是ES5 / 6或jQuery

const data = [{fromId: 1,toId: 2,finished: true},{fromId: 1,toId: 2,finished: false}, {fromId: 5,toId: 9,finished: false}, {fromId: 1,toId: 5,finished: true}, {fromId: 2, toId: 1, finished: false }];
var combos = [];
var  dupes = [];
var unique = [];

data.forEach(function(item){
  var combo = ""+item.fromId+"."+item.toId;
  if (combos.indexOf(combo) == -1) {
    combos.push(combo);
    unique.push(item);
  }
  else {
    dupes.push(item);
  }
});
console.log("dupes",dupes);
console.log("unique",unique,unique.length);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

答案 5 :(得分:0)

是的,有很多可用的选项...会用lodash/fp给您另一个选项:

假设您拥有:

import {flow, map, uniq} from 'lodash/fp'

执行以下操作:

const count = flow(
    map(o => o.fromId + '.' + o.toId),
    uniq,
  )(data).length

console.log('Count: ', count)