web-dev-qa-db-fra.com

comment utiliser un modèle de correspondance obtenir une liste non vide dans Scala

J'utilise la méthode case x :: Nil => ... afin de m'assurer que la liste est non vide, mais elle correspond simplement à la liste d'éléments uniques. Comment puis-je utiliser une correspondance de modèle pour obtenir une liste non vide?

MIS À JOUR
Je suis désolé, il semble que j'ai perdu quelque chose, il y a une scène spéciale utiliser le match interne,

object AccountResult{
  def unapply(account: AccountResult): Option[(String, List[String])] = ???
}

//ignore accountResult define please 
accountResult match {
  case AccountResult(_, x :: _) => ... 
}

comment puis-je faire correspondre la valeur de accountResult dont la valeur List [String] (x :: _) n'est pas Nil? et ensuite obtenir la valeur correspondante List [String]

10
LoranceChen

Au lieu de spécifier uniquement la liste vide avec Nil, spécifiez un élément pouvant être n'importe quelle liste, par exemple:

case x :: tail => ... // tail is a local variable just like x, holding the tail of the list

ou simplement:

case x :: _ => ...

si vous vous en fichez ou si vous n'utiliserez pas la queue.

Ces modèles correspondront à toute liste avec au moins un élément (plutôt que exactement un élément selon votre modèle existant). De même, le motif:

case x :: y :: the_rest => ...

correspondra à toute liste avec au moins deux éléments.

Edit (réponse à votre commentaire):

Vous pouvez affecter une variable dans un modèle de casse en utilisant "@". Donc, pour un exemple (d'utilisation typique) que vous avez peut-être déjà vu:

case acc@AccountResult(_, x :: tail) => ... // do something with 'acc'

ou, correspondant à l'utilisation que vous recherchez par votre commentaire:

case AccountResult(_, phone@(x :: tail)) => ... // do something with 'phone'
17
Shadowlands

Pour vérifier si la liste est non vide, vous pouvez associer un motif de cette façon:

list match {
   case Nil => false
   case _ => true
}

Ou

list match {
  case Nil => false
  case x::xs => true  
}
14
Nyavro

Si c'est quelque chose que vous utilisez souvent, vous pouvez créer un matcher personnalisé comme ceci:

object NonEmpty { 
  def unapply(l: List[_]) = l.headOption.map(_ => l)
}

Cela peut être utilisé comme ceci:

scala> List() match { case NonEmpty(l) => println(l) }
scala.MatchError: List() (of class scala.collection.immutable.Nil$)
  ... 33 elided

scala> List(43) match { case NonEmpty(l) => println(l) }
List(43)

scala> List(43, 32) match { case NonEmpty(l) => println(l) }
List(43, 32)
2
thoredge

Si vous voulez simplement assigner une liste entière non vide à un val, sans scinder tête et queue, vous ajoutez simplement un cas correspondant à une liste vide et un autre assignant la liste à un nom de variable comme celui-ci: 

accountResult match {
  case List() => ??? // empty case
  case myAccountResult => ??? //myAccountResult will contain the whole non-empty list  
}

Nil fait aussi le travail, en faisant correspondre une liste vide

accountResult match {
  case Nil => ??? // empty case
  case myAccountResult => ??? //myAccountResult will contain the whole non-empty list  
}
2
Visiedo