【问题标题】:How to add Options to a List如何将选项添加到列表
【发布时间】:2014-11-08 16:34:28
【问题描述】:

Options 添加到List 的最佳方法是什么。

这是我的第一次尝试:

def append[A](as: List[A], maybeA1 : Option[A], maybeA2: Option[A]) : List[A] = as  ++ maybeA1.toList ++ maybeA2.toList

Con : 它创建 2 tmp List

(我知道 .toList() 是可选的,因为存在从 Option[A] 到 Iterable[A] 的隐式转换)

另一个尝试是

def append2[A](ls: List[A], maybeA : Option[A]) : List[A] = maybeA.map(_ :: ls).getOrElse(ls)
def append[A](as: List[A], maybeA1 : Option[A], maybeA2: Option[A]) : List[A] = append2(append2(as, maybeA1), maybeA2)

性能更好,但可读性较差……

还有其他方法吗?

【问题讨论】:

  • 为什么要将 Option[A] 添加到 List[A]。你确定要看看有什么值得补充的吗?
  • 不要添加到列表的末尾。
  • 是的,我讨厌成为 Stack Overflow 上的那个人,但如果你发现自己在结尾,那么值得一问:你在这里使用 List 是否真的有原因(而不是其他类型的序列)?

标签: scala collections


【解决方案1】:
def combine[A](s: Seq[A], o: Option[A]) = (s /: o)(_ :+ _)
def combineAll[A](s: Seq[A], os: Option[A]*) = (s /: os)(combine)

combineAll(List(1), Some(2), None, Some(3))
//res0: Seq[Int] = List(1, 2, 3)

【讨论】:

  • 或者,为简洁起见:(s /: os)((l, o) => o.fold(l)(l :+ _))
  • @BenReich 谢谢,我把这个想法放进去了。它可能看起来像一个魔法虽然
【解决方案2】:

使用List.++List.++:

def append[A](o:Option[A],l:List[A]):List[A] = l ++ o   
def prepend[A](o:Option[A],l:List[A]):List[A] = o ++: l

【讨论】:

  • 您好,欢迎来到 SO!您能否对此添加一些解释?谢谢!
【解决方案3】:

您可以使用可变列表构建器

val builder = scala.collection.mutable.ListBuffer.empty[A]
builder ++= list
builder ++= maybe1
builder ++= maybe2
...
builder.result()

如果您有很多选项要添加,它可以提高性能,接近数千个,我认为在较小的数量上原始解决方案应该是好的

【讨论】:

    【解决方案4】:
    1. 您不能将Option[A] 添加到List[A]。您必须使用List[Option[A]],然后添加一个选项相当简单,或者对于每个选项,您必须检查它是否确实包含某些内容 (Some(a: A)),然后才将其添加到列表中。
    2. 如果列表中元素的顺序不是很重要,至少不是在添加阶段,那么最好使用:: 运算符将它们添加到开头而不是结尾。将元素添加到列表的开头需要恒定的时间。在末尾添加它们需要 O(n) 其中 n 是列表中已有元素的数量。那是因为程序必须先从头到尾遍历整个列表,然后才能添加新元素。

    因此,您的问题的答案将是:

    def add[A](ls: List[Option[A]], maybeA : Option[A]) = maybeA :: ls
    

    def add[A](ls: List[A], maybeA : Option[A]) = maybeA match {
      case Some(a) => a :: ls
      case None => ls
    }
    

    然后,在添加所有您喜欢的元素后,您只需调用ls.reverse 以按照您添加它们时的顺序排列它们。

    【讨论】:

    • 是的,您可以将Option[A] 添加到List[A]。只需启动一个 REPL 并粘贴此代码:List(1,2,3) ++ None ++ Some(4) ++ Some(5) ++ None 这与您的第二个解决方案完全相同,但要好得多。同时调用 ls.reverse 也会反转您的原始列表,这不是有意的。
    • 感谢您使用 case None => ls 修复该错误。但。 1.作者没有说上下文。这就是我第一次写“如果顺序不重要”的原因,因为也许它不重要,我们可以使用更快的::。此外,这添加了一个选项以使用++ 列出...好吧,它并没有真正添加一个选项。它添加 A 或什么都不添加:)
    • 1.根据定义,List 是有序的,因此在我看来,提供一个搞乱顺序的解决方案是不正确的。 2. 这个问题提供了两个例子来说明作者关于“向列表添加选项”的含义,如果您尝试过它们,您会发现它们确实是“添加 A 或不添加任何内容”。
    猜你喜欢
    • 1970-01-01
    • 2014-02-12
    • 1970-01-01
    • 2017-07-14
    • 1970-01-01
    • 1970-01-01
    • 2018-04-04
    • 1970-01-01
    相关资源
    最近更新 更多