給定一個列表[任何],我想將其轉換爲一個選項[列表[字符串]如何列表[任何]中選擇[列表[字符串]
def convert(ls: List[Any]) : Option[List[String]] = {
if (ls.forall(_.getClass == classOf[String]))
Some(ls.map(_.asInstanceOf[String]))
else
None
}
是否有轉換更好的方法 ?
給定一個列表[任何],我想將其轉換爲一個選項[列表[字符串]如何列表[任何]中選擇[列表[字符串]
def convert(ls: List[Any]) : Option[List[String]] = {
if (ls.forall(_.getClass == classOf[String]))
Some(ls.map(_.asInstanceOf[String]))
else
None
}
是否有轉換更好的方法 ?
有一個toString
方法,它可以從任何對象創建一個字符串。所以,如果它不是一個要求,即原來的列表中的所有元素實際上應該是字符串元素,你可以這樣做:
import scala.util.Try
def convert(l: List[Any]) : Option[List[String]] = {
Try(l.map(_.toString)).toOption
}
嘗試將返回一些(x)如果它成功,並獲得x的值,或無其它方式。
如果轉換成功,應該只有當所有的元素都是字符串,那麼我們可以做內部試轉換(在第一次失敗,嘗試將失敗,因此我們會得到無)
import scala.util.Try
def convert(l: List[Any]) : Option[List[String]] = {
Try(l.map(_.asInstanceOf[String])).toOption
}
正如在我的例子中,我想確保所有的元素都是字符串 – 2014-09-28 19:49:03
然後_.toString應該替換爲_.asInstanceOf [String]。 – Ashalynd 2014-09-28 19:57:09
哼哼......我更喜歡在之前檢查類型,而不是拋出異常(至少出於性能原因)。 – 2014-09-28 20:08:07
我會推薦使用的模式匹配:
def convert(l: List[Any]) : Option[List[String]] = {
Try(list.collect{
case s : String => s
case x : Any => throw new Exception()
}).toOption
}
正如在我的例子中,我想確保所有元素都是字符串 – 2014-09-28 19:50:29
我更新了答案,結合@Ashalynd解決方案與我的實現該 – 2014-09-28 19:59:22
嗡嗡聲...我更喜歡檢查類型而不是拋出異常。 – 2014-09-28 20:04:32
喜歡:
scala> val bag = List("a", 1, 2.0, "b")
bag: List[Any] = List(a, 1, 2.0, b)
scala> def unbagged(vs: List[Any]): Option[List[String]] = Option(vs collect { case s: String => s}) filter (_.nonEmpty)
unbagged: (vs: List[Any])Option[List[String]]
scala> unbagged(bag)
res0: Option[List[String]] = Some(List(a, b))
scala> unbagged(List(1, 3.14))
res1: Option[List[String]] = None
,或者尋址第e使用案例:
scala> def strung(vs: List[Any]): Option[List[String]] = (Option(vs) filter (_ forall { case _: String => true case _ => false })).asInstanceOf[Option[List[String]]]
strung: (vs: List[Any])Option[List[String]]
scala> strung(bag)
res3: Option[List[String]] = None
scala> strung(List("a","b","c"))
res4: Option[List[String]] = Some(List(a, b, c))
正如我的例子,我想確保所有元素都是字符串 – 2014-09-28 20:04:52
是的,我想我們錯過了那部分。 – 2014-09-28 20:24:02
imho,'_.isInstanceOf [String]'比'{case _:String => true case _ => false'更可讀, – 2015-06-22 20:19:17
代碼有點醜,但它的工作原理。 它不使用classOf
但它使用模式匹配:
scala> val l1 = List("a", 1, 12.0)
l1: List[Any] = List(a, 1, 12.0)
scala> val l2 = List[Any]("a", "b", "c")
l2: List[Any] = List(a, b, c)
scala> def convert(list: List[Any]) = {
| list.foldLeft(Some(List()): Option[List[String]]) { (x, y) =>
| x match {
| case Some(l) =>
| y match {
| case elem: String => Some(l ::: List(elem))
| case _ => None
| }
| case None => None
| }
| }
| }
convert: (list: List[Any])Option[List[String]]
scala> convert(l1)
res12: Option[List[String]] = None
scala> convert(l2)
res13: Option[List[String]] = Some(List(a, b, c))
scala>
已經有相當多的答案,但我認爲他們都是比需要聰明。在這個問題的初步建議並不壞,但我會通過isInstanceOf
更換getClass
測試:
def convert(ls: List[Any]): Option[List[String]] = {
if (ls.forall(_.isInstanceOf[String]))
Some(ls.map(_.asInstanceOf[String]))
else
None
}
它的功能,副本列表中只有一次。是的,列表遍歷了兩次,但通常它會比拋出異常更快(通常很慢 - 如果您真的想要走這條路,至少使用ControlThrowable
,它不記錄堆棧跟蹤當被構造時)。
此外,由於@ som-snytt在評論中悄悄指出,由於刪除,您甚至不需要將所有元素都放在列表中。你不妨也投了名單,其中,在已經檢查了所有的元素都是String
S,只是像任何其他類型轉換爲安全:
def convert(ls: List[Any]): Option[List[String]] = {
if (ls.forall(_.isInstanceOf[String]))
Some(ls.asInstanceOf[List[String]])
else
None
}
這是目前最有效的版本,因爲沒有列表根本不需要複製。
有使用scalaz一個簡單的解決方案:
def convert(ls: List[Any]) : Option[List[String]] =
ls.map { a => if (a.isInstanceOf[String]) Some(a.asInstanceOf[String]) else None}.sequence
我忘了,如果它是有效的Java或者喬希布洛赫要求,因爲它看起來像一個我們不使用ELL的瓦爾的謎題。在我升級眼鏡之前,我可能會開展一個推特活動。 :) – 2014-09-28 19:59:55
你是對的,我剛剛修好了 – 2014-09-28 20:16:22
其實,我認爲他的情況是很長的後綴,'1l',對此很抱歉;但我有相同的視覺解析問題。謝謝。 – 2014-09-28 20:19:29