我无法理解如何从一个阵列中拉出数组。
我尝试使用纯JavaScript(ES6):
let openTiles = [[1, 1], [2, 2], [1, 3]]
let usedTiles = [[1, 1], [2, 2]]
openTiles = openTiles.filter((item) => !usedTiles.includes(item))
我预计最终的openTiles是:[[1,3]]但它没有变化。问题是,上面的代码使用JavaScript的标准比较(===),它无法将一个数组与另一个数组进行比较。 Lodash有_.isEqual()函数,但我无法理解如何实现它。
我试过了:
openTiles = openTiles.filter((item) => {
return usedTiles.every((el) => {
_.isEqual(item, el)
})
})
但这给了我一个空数组。我想看看人们如何合并Lodash的_.isEqual()函数,以便可以从openTiles中删除usedTiles中的所有数组。
而不是尝试编写通用对象或数组等于函数,或使用来自lodash,Ramda,下划线等的函数,您可以编写一个特定于您的类型的函数。如果你的tile只是两个元素的数组,那么只需编写一个反映它的equals
函数。然后你可以在some
中使用它:
const tilesEqual = (a) => (b) => a[0] == b[0] && a[1] == b[1]
const removeTiles = (open, used) => open.filter(
tile => !used.some(tilesEqual(tile))
)
let openTiles = [[1, 1], [2, 2], [1, 3]]
let usedTiles = [[1, 1], [2, 2]]
console.log(removeTiles(openTiles, usedTiles))
至于为什么上面的代码不起作用,有两个问题。您不想知道every
使用的瓷砖是否与您当前的瓷砖匹配。你只想知道他们做的some
。那么因为那些是你要删除的,你需要为filter
否定这个。所以你想要像!usedTiles.some(...)
这样的东西。
但还有另一个问题。你不会在回调中向every
/ some
返回任何内容:
return usedTiles.every((el) => {
_.isEqual(item, el)
})
您需要将其切换为其中之一
return usedTiles.every((el) => _.isEqual(item, el))
要么
return usedTiles.every((el) => {
return _.isEqual(item, el)
})
这是一个容易犯的错误,而且很常见。如果你使用带有{
-}
分隔块的箭头函数,你需要一个return
语句。
一个简单的方法是对要比较的数组进行字符串化,以便.includes
正常工作:
let openTiles = [[1, 1], [2, 2], [1, 3]]
let usedTiles = [[1, 1], [2, 2]]
const usedTilesStringified = usedTiles.map(JSON.stringify);
openTiles = openTiles.filter((item) => !usedTilesStringified.includes(JSON.stringify(item)))
console.log(openTiles);
或者您可以明确地比较每个值:
let openTiles = [[1, 1], [2, 2], [1, 3]];
let usedTiles = [[1, 1], [2, 2]];
openTiles = openTiles.filter((item) => {
const { length } = usedTiles;
outer:
for (let i = 0, { length } = usedTiles; i < length; i++) {
const usedTile = usedTiles[i];
if (usedTile.length !== item.length) {
continue;
}
for (let j = 0, { length } = usedTile; j < length; j++) {
if (usedTile[j] !== item[j]) {
// The current subarrays being compared are not identical:
continue outer;
}
}
// We've iterated through all indicies while comparing one subarray to another
// they all match, so the arrays are the same, so this filter fails:
return false;
}
return true;
})
console.log(openTiles);
对于不太通用的解决方案,只检查索引0是否等于索引1:
let openTiles = [[1, 1], [2, 2], [1, 3]];
let usedTiles = [[1, 1], [2, 2]];
openTiles = openTiles.filter((item) => {
for (let i = 0, { length } = usedTiles; i < length; i++) {
const usedTile = usedTiles[i];
if (usedTile[0] === item[0] && usedTile[1] === item[1]) {
return false;
}
}
return true;
})
console.log(openTiles);
从另一个lodash中减去一个数组包含一系列差异方法。
由于您的案例中的值是一个数组,因此简单的相等不起作用,因为[] !== []
。 Lodash的_.isEqual()
对两个值进行了深入的比较。
要将差异减法与_.isEqual()
结合使用,请使用_.differenceWith()
。
let openTiles = [[1, 1], [2, 2], [1, 3]]
let usedTiles = [[1, 1], [2, 2]]
openTiles = _.differenceWith(openTiles, usedTiles, _.isEqual)
console.log(openTiles)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>