Reputation: 4820
Specifically, I have an ImmutableJS List of Maps, and I want to conditionally update records to the same value (which may include just updating all of them). The use case is revealing mines in minesweeper, when someone loses the game. this is accomplished by setting the isVisible
tile to true, if isMine
is also true (or just make every tile visible, regardless of isMine
)
so my JS schema is like this (where arrays are lists and objects are maps):
game = {
isGameOver: false,
tiles: [
{
isMine: boolean,
isRevealed: boolean
},
...
]
}
and so what I'm trying to do is, starting with game
, set isRevealed
to true for every tile where isMine
is true.
this is what i came up with, but it looks so awful I have to hope there's another way
function revealAll(game){
let revealedTiles;
revealedTiles = game.get('tiles').map(tile => {
if (tile.get('isMine')) {
tile = tile.set('isRevealed', true);
}
return tile;
});
return game.set('isGameOver', true).set('tiles', revealedTiles);
}
this successfully ends the game (sets isGameOver
to true) and reveals all tiles that are mines (sets isRevealed
to true for every tile with isMine
equal to true), but I can tell just looking at it that its both inefficient and messy. Is there a built in way to accomplish what i'm doing here?
Upvotes: 2
Views: 1007
Reputation: 913
Here's a functional programming approach using mudash. The benefit of this approach is that mudash will handle both ImmutableJS data types as well as standard JS (or a mix of both). So your function can be used no matter the format.
import _ from 'mudash'
import fp from 'mudash/fp'
const revealAll = _.compose(
fp.set('isGameOver', true),
fp.update('tiles', fp.map((tile) =>
_.update(tile, 'isRevealed', (isRevealed) => _.get(tile, 'isMine') || isRevealed)))
)
const gameMutable = {
isGameOver: false,
tiles: [
{
isMine: false,
isRevealed: false
},
{
isMine: true,
isRevealed: false
},
{
isMine: false,
isRevealed: true
},
{
isMine: true,
isRevealed: true
}
]
}
const gameImmutable = _.immutable(gameMutable)
console.log(revealAll(gameMutable))
console.log(revealAll(gameImmutable))
Upvotes: 0
Reputation: 15638
From my point of view, the code is quite fine :) There are however few tricks that may make it nicer:
using multiple set
on the same Map
can be replaced by one merge
:
return game.merge({
'isGameOver': true,
'tiles': revealedTiles
});
Also, updating an individual tile can be done nicer:
revealedTiles = game.get('tiles').map(
tile => tile.update('isRevealed', (v) => tile.get('isMine') || v))
so you end up with:
function revealAll(game){
let revealedTiles
revealedTiles = game.get('tiles').map(
tile => tile.update('isRevealed', (v) => tile.get('isMine') || v))
return game.merge({
'isGameOver': true,
'tiles': revealedTiles
});
}
OR, you can do it like this:
const revealAll = (game) =>
game
.set('isGameOver', true)
.update('tiles', (tiles) => tiles.map(
tile => tile.update('isRevealed', (v) => tile.get('isMine') || v)))
Upvotes: 1