成对地从数组中删除元素
Pairwise remove elements from array
我想要一个函数 (collisions
),当它们太相似时可以从数组中删除对象。
我有一个可以工作的版本,但是太丑了,我不想提交。
设置
在我的 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)
);
}
如果他们不这样做,两艘船都会沉没。
(这是需要重构的部分)
// 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);
}
}
在上面的设置中,我希望只有 C
和 F
的船能够存活。
console.log("Boats at start:", boats.map((boat => boat.name)));
collisions()
console.log("Boats left over:", boats.map((boat => boat.name)));
问题
所以我的问题是:如何使函数 collisions
更简单且更具可读性?
我不明白你为什么要保存索引而不是船...检查一下:
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
)
但是你可以采用这样一种更具可读性的函数式方式:
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)
最终版本
正如 @pilchard 指出的那样,您可以使用 some
提高性能(即使在 10x10 sheet 中您不会看到这样的改进):
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)
我想要一个函数 (collisions
),当它们太相似时可以从数组中删除对象。
我有一个可以工作的版本,但是太丑了,我不想提交。
设置
在我的 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)
);
}
如果他们不这样做,两艘船都会沉没。 (这是需要重构的部分)
// 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);
}
}
在上面的设置中,我希望只有 C
和 F
的船能够存活。
console.log("Boats at start:", boats.map((boat => boat.name)));
collisions()
console.log("Boats left over:", boats.map((boat => boat.name)));
问题
所以我的问题是:如何使函数 collisions
更简单且更具可读性?
我不明白你为什么要保存索引而不是船...检查一下:
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
)
但是你可以采用这样一种更具可读性的函数式方式:
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)
最终版本
正如 @pilchard 指出的那样,您可以使用 some
提高性能(即使在 10x10 sheet 中您不会看到这样的改进):
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)