【问题标题】:Idiomatic way of prepending Option[A] to Option[List[A]]将 Option[A] 附加到 Option[List[A]] 的惯用方式
【发布时间】:2013-05-21 09:05:27
【问题描述】:

我有:ox: Option[A]oxs: Option[List[A]]

我想:

  • 如果两者都存在,则返回 ox.get :: oxs.get

  • 如果ox 存在而oxs 不存在,则返回List(ox.get)

  • 如果oxs 存在而ox 不存在,则返回oxs.get

  • 如果两者都是None,则返回List()

我可以通过ifs 和matches 实现这一点。我只是想知道是否有任何优雅的惯用方式?

编辑:我已经测试过:List(ox.map(List(_)), oxs).flatten.flatten,它似乎适用于所有四种情况,但看起来仍然有点难以理解。

【问题讨论】:

  • 你试过flatten 吗? prolly 这可能会有所帮助.. stackoverflow.com/questions/4730842/…
  • @Shrey:我试过List(ox.map(List(_)), oxs).flatten.flatten。虽然我得到的类型匹配,但它似乎太疯狂了。

标签: scala


【解决方案1】:
val oa: Option[A] = ???
val oas: Option[List[A]] = ???

val result = oa ++: oas.getOrElse( Nil ) // O(1).
val result2 = oa ++: oas.flatten // 2.9.x only. same result, less performance (O(N)).
val result3 = oa ++: oas.toList.flatten // 2.10.x. O(N).

Flatten 在result2 中创建新的Listresult 重用初始列表:

val oa = Some(1)
val as = List(2,3)
val oas = Option(as)

val result = oa ++: oas.getOrElse( Nil )
// List(1, 2, 3)

val result2 = oa ++: oas.flatten
// List(1, 2, 3)

result.tail eq as // true - same object

result2.tail eq as // false - new object

【讨论】:

  • 虽然 result2 的性能可能较差,但从可读性的角度来看,我喜欢它(我的列表会很短,并且此操作将在关键循环之外)
  • 谢谢! FP 的强大和富有表现力真是令人惊叹。
【解决方案2】:

试试,

ox.toList ++ oxs.toList.flatten

如果您不介意结果是 Iterable[Int] 而不是 List[Int],您可以删除最初的 toList

ox ++ oxs.toList.flatten

【讨论】:

  • flatten 之前明确提及toList 有什么特别的原因吗?
  • @senia flattenList[List[T]] 上可用,但在Option[List[T]] 上不可用。
  • @MilesSabin 有一个隐含的Option.option2Iterable
  • @MilesSabin:谢谢。我只在2.9.3 上测试过,在Option2.9.3 中没有flatten 方法。
  • @senia 好记...是的,在 2.9.x 上第二个 toList 可以删除。
【解决方案3】:

你也可以使用 for 理解:

for (x <- ox; xs <- oxs) yield x :: xs

这只是一种更好的写作方式

ox.flatMap(x => oxs.map(xs => x :: xs))

【讨论】:

  • for 理解仅在两者都不是None 的情况下有效。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-21
  • 2019-03-03
  • 2012-02-08
  • 2012-02-08
  • 2021-08-31
  • 1970-01-01
相关资源
最近更新 更多