【问题标题】:Need to use an object to filter with lodash and include a between condition需要使用一个对象来过滤 lodash 并包含一个 between 条件
【发布时间】:2018-03-15 20:04:20
【问题描述】:

我们制作了一个视频游戏数据库,我们需要按游戏和排名过滤人们。该对象的结构如下:

[{
    "key": 86,
    "position": [
      40.369,
      -3.5419
    ],
    "info": {
      "gamesplaying": [
        {
          "gameid": 2,
          "rankid": 8
        },
        {
          "gameid": 4,
          "rankid": 8
        },
        {
          "gameid": 5,
          "rankid": 14
        }
      ],
      "city": "Kersey",
      "age": 42,
      "name": "Fisher Hayden",
      "id": 2
    }
  },
  {
    "key": 87,
    "position": [
      40.554,
      -3.7578
    ],
    "info": {
      "gamesplaying": [
        {
          "gameid": 2,
          "rankid": 2
        }
      ],
      "city": "Ahwahnee",
      "age": 24,
      "name": "Aurora Rivers",
      "id": 35
    }
  }]

我们需要按游戏 id 和排名 id 执行过滤,当使用对象而不是函数作为过滤器时,_.filter 似乎对我们有帮助。这不介意游戏数组中的元素数量或顺序,所以它完美!性能比几个嵌套的 for 循环要好得多,所以我们希望保留这个函数。

我们的问题是我们现在添加了一个年龄过滤器。所以我们不需要一个确切的年龄,而是两个值之间的年龄。

函数现在看起来像这样:

 let markers = this.props.markers;

    if(this.state.rankidFilter > 0 || this.state.gameidFilter > 0 || this.state.minAgeFilter > 0 || this.state.maxAgeFilter > 0) {

      let gameFilters = {};
      if (this.state.gameidFilter > 0) gameFilters = {...gameFilters, gameid: parseInt(this.state.gameidFilter, 10)};
      if (this.state.rankidFilter > 0) gameFilters = {...gameFilters, rankid: parseInt(this.state.rankidFilter, 10)};

      let newMarkers =_.filter(this.props.markers, {info: {gamesplaying: [gameFilters]}});

      markers = newMarkers;
    }

我们尝试了一些东西来为年龄属性添加过滤对象函数或条件,因此值介于 2 个数字之间,但我们没有找到正确的方法。

请帮忙,我们想保留 _.filter 功能。提前致谢

编辑:像 {info: {gamesplaying: [{gameid: parseInt(this.state.gameidFilter, 10), rankid: parseInt(this.state.rankidFilter, 10)}]} 的对象,age: _.between (20, 55)} 在该值中考虑一系列年龄

【问题讨论】:

    标签: javascript json reactjs lodash


    【解决方案1】:

    如果您想使用单个 lodash 过滤器而不是链接多个过滤器来执行此操作,您可以执行类似的操作,对第二个 _.filter 参数使用函数而不是对象:

    markers = _.filter(markers, o =>
        (!this.state.minAgeFilter || (o.info.age >= this.state.minAgeFilter))
            && (!this.state.maxAgeFilter || (o.info.age <= this.state.maxAgeFilter))
            && (!this.state.gameidFilter || _.find(o.info.gamesplaying, { gameid: this.state.gameidFilter }))
            && (!this.state.rankidFilter || _.find(o.info.gamesplaying, { rankid: this.state.rankidFilter })));
    

    这会将您的&gt; 0 检查直接组合到过滤器表达式中。对于this.state 中的每个潜在过滤器,如果过滤器为假(null、不存在或 0),则行的 !this.state.fooFilter || 部分会短路表达式。如果 fooFilter 值大于 0,则评估该行的后半部分。对于年龄过滤器,我们相应地比较&gt;=&lt;=,对于gameid 和rankid 过滤器,我们使用_.find 来检查数组中是否存在具有匹配id 的对象。请注意,这些连接的 &amp;&amp; 表达式按评估成本从低到高排序(将 _.find 调用放在列表后面),因此短路评估可能会为我们节省一些时间。

    关于您的原始代码的几点说明:

    • 我不确定为什么上面的代码在您已经直接将它们与上面的 if 条件中的 0 进行比较之后对 idfilter 数字执行 parseInt
    • 您不需要临时变量 newMarkers 来使用单行 lodash 过滤器方法存储值。

    编辑添加:Jorge 正确地指出,我的_.find 子句将使过滤器返回包含具有gameid 和rankid 的单个游戏的任何对象,不一定在同一个游戏中。我们可以通过各种方式将这些组合成一个单一的发现。这是一种方法:

    const gameFilter = {};
    if (this.state.gameidFilter) {
        gameFilter.gameid = this.state.gameidFilter;
    }
    if (this.state.rankidFilter) {
        gameFilter.rankid = this.state.rankidFilter;
    }
    
    markers = _.filter(markers, o =>
        (!this.state.minAgeFilter || (o.info.age >= this.state.minAgeFilter))
            && (!this.state.maxAgeFilter || (o.info.age <= this.state.maxAgeFilter))
            && (_.size(gameFilter) === 0 || _.find(o.info.gamesplaying, gameFilter)));
    

    在同时提供 gameidFilter 和 rankidFilter 的情况下,只有在 gamesplaying 数组中存在具有正确 gameid 和正确 rankid 的游戏时,find 才会返回真值(找到的对象)。否则 find 将返回虚假的undefined,导致_.filter 表达式的计算结果为false

    【讨论】:

    • 这是我第一次尝试 lodash :P,所以从今天开始有很多乱七八糟的东西......我需要在测试后做很多清理工作,甚至不记得为什么那个解析就在那里,我认为是因为几个小时前的一些 ESLint 警告。所以有两件事,首先,感谢这个解决方案,因为这是我想要的方式。我需要做的唯一更正是 rankid 和 gamid 需要与过滤器值位于同一对象中。您的解决方案在数组中的不同对象中找到其中一个。非常感谢你,因为它可以满足我对年龄的要求。你会推荐嵌套的 _.filter 吗?
    • 好点!我已经更新了答案以添加另一种更正您提出的问题的方法。这也可以通过其他方式实现,例如使用嵌套或链式过滤器,这些方式可能更易于人类阅读。
    • 好的,它只是为了可读性,还是嵌套过滤器示例会执行得更好。在这种情况下,我们需要这部分代码尽可能快,哈哈哈,只需阅读您的编辑,这与我在为这两个条件应用条件过滤时所做的方法相同。所以看来我的结构是正确的,谢谢你的帮助!
    • 老实说,我并没有那么担心 JavaScript 优化,所以我不是回答性能问题的最佳人选……但总的来说,我希望短路评估表达式更快比多个函数调用。
    猜你喜欢
    • 2015-03-31
    • 1970-01-01
    • 2015-04-06
    • 2021-10-26
    • 2018-02-23
    • 2015-06-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多