【问题标题】:Update multiple entries in an ImmutableJS List更新 ImmutableJS 列表中的多个条目
【发布时间】:2016-04-05 18:06:17
【问题描述】:

具体来说,我有一个 ImmutableJS 地图列表,我想有条件地将记录更新为相同的值(可能包括更新所有记录)。当有人输掉游戏时,用例是在扫雷中揭示地雷。这是通过将isVisible 磁贴设置为真来完成的,如果isMine 也是真的(或者只是让每个磁贴可见,不管isMine

所以我的 JS 架构是这样的(其中数组是列表,对象是映射):

game = {
  isGameOver: false,
  tiles: [
    {
      isMine: boolean,
      isRevealed: boolean
    },
    ...
  ]
}

所以我想要做的是,从game 开始,为isMine 为真的每个图块设置isRevealed 为真。

这是我想出来的,但它看起来太糟糕了,我不得不希望有另一种方法

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);
}

这成功地结束了游戏(将isGameOver 设置为真)并显示所有属于我的图块(将isRevealed 设置为真,对于isMine 等于真的每个图块),但我可以看出来它既低效又混乱。有没有内置的方法来完成我在这里所做的事情?

【问题讨论】:

  • 它似乎没有什么可怕的问题,但如果你非常担心它,只需在映射列表之前使用 .withMutations 。但实际上,对于非性能关键代码中的几百个对象,似乎不值得考虑太多。

标签: javascript list dictionary immutable.js


【解决方案1】:

从我的角度来看,代码非常好 :) 但是有一些技巧可以使它变得更好:

在同一个Map上使用多个set可以用一个merge代替:

return game.merge({
    'isGameOver': true,
    'tiles': revealedTiles
});

此外,更新单个图块可以做得更好:

revealedTiles = game.get('tiles').map(
    tile => tile.update('isRevealed', (v) => tile.get('isMine') || v))

所以你最终得到:

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
    });
}

或者,你可以这样做:

const revealAll = (game) =>
    game
    .set('isGameOver', true)
    .update('tiles', (tiles) => tiles.map(
        tile => tile.update('isRevealed', (v) => tile.get('isMine') || v)))

【讨论】:

    【解决方案2】:

    这是一种使用mudash 的函数式编程方法。这种方法的好处是 mudash 将处理 ImmutableJS 数据类型以及标准 JS(或两者的混合)。所以无论格式如何,你的函数都可以使用。

    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))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-21
      • 2019-02-03
      • 2013-01-22
      相关资源
      最近更新 更多