【问题标题】:How to filter an ArrayBuffer of JsObject to remove items having a specific value如何过滤 JsObject 的 ArrayBuffer 以删除具有特定值的项目
【发布时间】:2014-08-12 01:48:45
【问题描述】:

我的 play 2.3 应用程序中有以下变量

private var messages = ArrayBuffer[JsObject]()

我想从消息中删除所有具有特定键值“message_id”的元素。我目前的实现如下

messages = messages.filterNot{item =>
    if ((item \ "message_id").as[Int] == myMessageId){
        true
    } else {
        false
    }
}

这行得通,但我几乎可以肯定我错过了一种更优雅的类似 scala 的方式来完成同样的事情。过滤包含特定键/值对的 JsObject 的惯用方法是什么?

【问题讨论】:

  • 一般来说,您不需要 if/else - 直接使用条件 messages.filterNot{item =>(item \ "message_id").as[Int] == myMessageId}。不过,Ryan 的回答更适合您的具体情况

标签: scala playframework playframework-2.3


【解决方案1】:

您可以使用 Play 的 Reads 转换器。

val messageId = (__ \ "message_id").read[Int].filter(_ == myMessageId)

messages = messages.filter(_.validate(messageId).isSuccess)

这也将处理 message_id 不存在或不知何故不是 int 的情况,但根据您的用例,您可能不想默默地丢弃该错误。

【讨论】:

  • 这似乎是过滤所有具有该键的整数值的 JsObject 的好方法,但我如何使用此模式过滤该键的特定值?例如:我想从包含 {"message_id" => 1} 但不包含 {"message_id" => 2} 的 ArrayBuffer 中删除所有 JsObjects。
  • 在下面我的解决方案中使用 filter(_ == 123) 和使用 (verifying[Int](_ == 123)) 有什么真正的区别吗?
【解决方案2】:

我找到了两种方法,每一种都是 Ryan 和 Paul 的想法的变体。

首先是使用play.api.libs.json.ConstraintReads 中的“验证”方法来细化 Ryan 建议的 Reads 转换器,使其仅匹配特定值:

val messageId = (__ \ "message_id").read[Int](verifying[Int](_ == 123))
messages = messages.filterNot{_.validate(messageId).isSuccess}

第二种方法是按照 Paul 的建议直接从 JsObject 中选择字段,但使用asOpt[T] 以确保在键不存在或值类型错误时不会引发异常:

messages = messages.filterNot{x => (x \ "message_id").asOpt[Int] == Some(123)}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-09-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-05
    相关资源
    最近更新 更多