简体   繁体   English

从数组中成对删除元素

[英]Pairwise remove elements from array

I want a function ( collisions ) that can remove object from an array when they are too similar.我想要一个函数( collisions ),当它们太相似时可以从数组中删除对象。 I have a working version, but it is so ugly that I don't want to commit it.我有一个工作版本,但它太丑了,我不想提交。

Setup设置

In my 10x10 pool I have a lot of boats:在我的 10x10 游泳池中,我有很多船:

var boats = [
  {name: "A", position: [1,1] }, // collides with E and G
  {name: "B", position: [7,8] }, // collides with D
  {name: "C", position: [8,2] }, // will not collide
  {name: "D", position: [7,9] }, // collides with B
  {name: "E", position: [2,1] }, // collides with A and G
  {name: "F", position: [1,7] }, // will not collide
  {name: "G", position: [2,2] }, // collides with A and E
]

Ships need to be carefull not to get to close to other boats.船只需要小心不要靠近其他船只。

const collisionDistance = 5;

function distance(boat1, boat2) {
  return Math.sqrt(
    Math.pow(boat1.position[0] - boat2.position[0], 2) +
    Math.pow(boat1.position[1] - boat2.position[1], 2)
  );
}

If they fail to do so both boats will sink.如果他们不这样做,两艘船都会沉没。 (this is the part that needs refactoring) (这是需要重构的部分)

// Boats that are too close to another boat are removed from the list of boats
// How can I make this beautiful?
function collisions() {
  var collidingBoatIndices = new Set();
  // iterate over pairs of the list
  for (let i = 0; i < boats.length; i++) {
    for (let j = i+1; j < boats.length; j++) {
      if (distance(boats[i], boats[j]) < collisionDistance) {
        collidingBoatIndices.add(i);
        collidingBoatIndices.add(j);
      }
    }
  }
  // delete from biggest to smallest index so there is no shift in the elements
  for (let index of Array.from(collidingBoatIndices).sort().reverse()){
    console.log("Boat sank: ", boats[index])
    boats.splice(index, 1);
  }
}

In the setup above I expect only boats C and F to survive.在上面的设置中,我希望只有船CF能够生存。

console.log("Boats at start:", boats.map((boat => boat.name)));
collisions()
console.log("Boats left over:", boats.map((boat => boat.name)));

Question

So my question is: How can I make the function collisions simpler and more readable?所以我的问题是:如何让函数collisions更简单、更易读?

I don't get it why you are saving the indexes instead of the boats... check this:我不明白你为什么要保存索引而不是船......检查这个:

 var boats = [ {name: "A", position: [1,1] }, // collides with E and G {name: "B", position: [7,8] }, // collides with D {name: "C", position: [8,2] }, // will not collide {name: "D", position: [7,9] }, // collides with B {name: "E", position: [2,1] }, // collides with A and G {name: "F", position: [1,7] }, // will not collide {name: "G", position: [2,2] }, // collides with A and E ] const collisionDistance = 5; function distance(boat1, boat2) { return Math.sqrt( Math.pow(boat1.position[0] - boat2.position[0], 2) + Math.pow(boat1.position[1] - boat2.position[1], 2) ); } const res = [] for(let i = 0; i < boats.length ; i++){ let flag = true; for(let j = 0; j < boats.length; j++){ if(distance(boats[i], boats[j]) < collisionDistance && i != j){ flag = false; } } if(flag){ res.push(boats[i]) } } console.log( res )

But you can take a way more readable functional way like this:但是您可以采用一种更具可读性的功能方式,如下所示:

 var boats = [ {name: "A", position: [1,1] }, // collides with E and G {name: "B", position: [7,8] }, // collides with D {name: "C", position: [8,2] }, // will not collide {name: "D", position: [7,9] }, // collides with B {name: "E", position: [2,1] }, // collides with A and G {name: "F", position: [1,7] }, // will not collide {name: "G", position: [2,2] }, // collides with A and E ] const collisionDistance = 5; function distance(boat1, boat2) { return Math.sqrt( Math.pow(boat1.position[0] - boat2.position[0], 2) + Math.pow(boat1.position[1] - boat2.position[1], 2) ); } const res = boats.filter( (b1, i) => boats.every( (b2, j) => !(distance(b1, b2) < collisionDistance && i != j) ) ) console.log(res)

Final version最终版本

As @pilchard pointed out, you can increase the performance by using some (even though in a 10x10 sheet you won't see such a improvement):正如@pilchard指出的,您可以通过使用some来提高性能(即使在 10x10 的工作表中您不会看到这样的改进):

 var boats = [ {name: "A", position: [1,1] }, // collides with E and G {name: "B", position: [7,8] }, // collides with D {name: "C", position: [8,2] }, // will not collide {name: "D", position: [7,9] }, // collides with B {name: "E", position: [2,1] }, // collides with A and G {name: "F", position: [1,7] }, // will not collide {name: "G", position: [2,2] }, // collides with A and E ] const collisionDistance = 5; function distance(boat1, boat2) { return Math.sqrt( Math.pow(boat1.position[0] - boat2.position[0], 2) + Math.pow(boat1.position[1] - boat2.position[1], 2) ); } const res = boats.filter( (b1, i) => !boats.some( (b2, j) => distance(b1, b2) < collisionDistance && i != j ) ) console.log(res)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM