【问题标题】:how to quickly compare all elements in an array如何快速比较数组中的所有元素
【发布时间】:2019-08-18 08:05:40
【问题描述】:

我有一个包含 100 个元素的字符串,并且该数组有 100 个对象。这些对象具有 X 和 y 值。我想找到具有相同 X 和 y 值的元素。我该怎么做?

 for (var i = 0; i < circleArray.length; ++i) {
                for (var j = 1; j < circleArray.length; ++j)
                    if (circleArray[i].x == circleArray[j].x && circleArray[i].y == circleArray[j].y) {
                        console.log("mission completed");
                    }
            }

我按照上面的方式进行操作,但它会消耗大量性能并且运行速度非常慢。

所有代码:https://codepen.io/tolgaand/pen/PoYzaKP

【问题讨论】:

  • 你想要的输出是什么?您是否只想知道数组中的两个元素是否具有相同的 x 和 y 坐标? (所以true/false 值来表明这一点)
  • 你能分享一些示例数据吗
  • summit:代码:codepen.io/tolgaand/pen/PoYzaKP Nick Parsons:是的,我想删除具有相同 x 和 y 值的对象。
  • @TolgaÇağlayan — 将所有信息放在原始帖子中,而不是 cmets。链接的代码不包括示例数据或输出(应该在 OP 中)。

标签: javascript html arrays object html5-canvas


【解决方案1】:

我们可以使用Set根据xy这两个属性来判断是否遇到了重复元素,如果是重复的我们将其添加到dup数组中:

const circleArray = [{x: 100, y: 200, c: 30}, {x:50, y:40, c:56}, 
                     {x:23, y:78, c:90}, {x:50, y:40, c:78}, 
                     {x:23, y:78, c:98}, {x:2, y:378, c:90}, 
                     {x:237, y:8, c:10}];
                     
//To get the duplicate objects
const seen = new Set();
const dup = circleArray.reduce((acc, obj) => {
  //if size is same, the object is a duplicate based on x and y props
  if(seen.size === seen.add(obj.x + "|" + obj.y).size){ 
    acc.push(obj);
  }
return acc;
}, []);
console.log(dup);

要删除重复项,我们可以使用Array.prototype.filter 根据xy 属性将重复对象过滤到一个新数组中:

//To remove duplicates 
const circleArray = [{x: 100, y: 200, c: 30}, {x:50, y:40, c:56}, 
                         {x:23, y:78, c:90}, {x:50, y:40, c:78}, 
                         {x:23, y:78, c:98}, {x:2, y:378, c:90}, 
                         {x:237, y:8, c:10}];
                         
const seen = new Set();
const filtered = circleArray.filter((obj) => {
 //if size is same, the object is a duplicate based on x and y props
 return seen.size !== seen.add(obj.x + "|" + obj.y).size
});
console.log(filtered);

【讨论】:

  • 这不适用于某些值,尤其是那些不以 0 结尾的值。
  • @JackBashford 嘿,杰克,你能举个例子吗?我会尝试修复代码
  • 如果x23 并且y78,那将如何区分x: 2, y: 378x: 237, y: 8
  • @JackBashford 是的,好点,我认为分隔符可以解决它吗?
【解决方案2】:

使用some - 一旦找到匹配对,它就会停止:

if (circleArray.some(({ x, y }, i) => circleArray.some(({ x: x2, y: y2 }, j) => i != j && x == x2 && y == y2))) {
    console.log("Mission completed!");
}

【讨论】:

  • 这难道不是总是正确的,因为每个元素都在与自身进行比较,因此每个元素总是有一个匹配对(至少它自己)?您需要根据我认为的索引进行拆分。
  • 就像您尝试使用[{"x":1,"y":2},{"x":1,"y":3},{"x":1,"y":5}] 一样,即使没有匹配项,该语句的计算结果也会为真。
  • 固定@rb612,更好吗?
【解决方案3】:

您可以在每次迭代中排除相同的项目,这样下一个循环的迭代次数就会减少。当你没有相同的对象时,最坏的情况会发生。

            circleArray.splice(j, 1);

完整代码

for (var i = 0; i < circleArray.length; ++i)
{

    for (var j = 1; j < circleArray.length; ++j)
        if (circleArray[i].x == circleArray[j].x && circleArray[i].y == circleArray[j].y)
        {
            console.log("mission completed")
            circleArray.splice(j, 1);
        }
}



【讨论】:

    【解决方案4】:

    我的理解是删除两个重复项。如果这不正确,请澄清要求。看不懂OP与链接代码有什么关系,以下是根据OP中的代码来的。

    一种方法是创建一个值索引,该索引引用circleArray 中相关对象的索引。当找到重复项时,它们的索引被添加到 remove 数组中。 remove 数组被循环以删除所有重复项。这将遍历原始数组并每次复制一次数组。

    通过在 remove 数组中的等价索引处插入要删除的索引,简化了逻辑,要删除的索引保持顺序而不进行排序,而 remove 数组保持尽可能小,因此最终的 reduceRight 仅根据需要多次迭代(reduceRight 仅访问存在的元素,例如 [,1,,,,5] 只会迭代两次)。

    let circleArray = [
      {x: 0, y:0},
      {x: 5, y:5},  // dupe
      {x: 1, y:1},
      {x: 2, y:2},  // dupe
      {x: 2, y:2},  // dupe
      {x: 5, y:5},  // dupe
      {x: 3, y:3},  // dupe
      {x: 4, y:4},
      {x: 5, y:5},  // dupe
      {x: 3, y:3},  // dupe
      {x: 6, y:6},
      {x: 5, y:5}   // dupe
    ];
    
    function removeDupes(arr) {
    
      // Array of indexes to remove
      let remove = [];
    
      // Get indexes to remove
      arr.reduce((acc, obj, i) => {
    
        // Create key from x and y values
        let idx = obj.x + ':' + obj.y;
    
        // If it's dupe, add it and the initial dupe to the remove array
        if (acc[idx]) {
          remove[i] = i;
          remove[acc[idx].idx] = acc[idx].idx;
    
        // Otherwise, just add it to the index (don't need dupes in index)
        } else {
          acc[idx] = {idx: i};
        }
        return acc;
      }, Object.create(null));
    
      // Go backwards over remove and splice dupes
      remove.reduceRight((acc, idx) => circleArray.splice(idx, 1), null);
    }
    
    removeDupes(circleArray);
    
    console.log(circleArray)

    只有测试才能知道这是否比其他方法更快,并且不同方法的性能在不同的实现中可能会有所不同。

    更好的方法可能是首先避免创建重复项,例如通过在将它们放入 circeArray 时维护值的索引而不插入重复项。

    【讨论】:

      【解决方案5】:

      我认为您可以使用 JavaScript 数组方法 .map()、.reduce()、.filter() 来实现这一点。和.find()。 PFB 示例代码。

      var arrA=[{x:10,y:20},{x:30,y:40},{x:50,y:60}];
      var arrB=[{x:12,y:20},{x:21,y:40},{x:51,y:60},{x:50,y:60}];
      
      var result = arrA.map(function (ele, i) {
            var res=arrB.find(function(item, index, array) {
              return (item.x==ele.x && item.y==ele.y) ? (item['j']=index) : null;
            });
            if(res !=null){ res['i']=i;}
            return res;
      });
      var finalresult= result.filter(item => item !=null);
      

      输出:[{"x":50,"y":60,"j":3,"i":2}]

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-08-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-01-13
        • 1970-01-01
        相关资源
        最近更新 更多