0
votes

Scala a-t-il un équivalent efficace à la fonction SEQ.TRAPICK de F #?

Supposons que j'ai une séquence myseq code> consistant en éléments de type a code> et une fonction f code> de type a -> option code>, et je veux le premier résultat de type Option code> c'est un un code> résultant de l'application f code> à tous Éléments de la séquence, sinon Aucun code> si aucun résultat de ce type n'a été trouvé.

in f # Ceci est soigneusement géré par le Trypick code> Fonction: P >

mySeq.iterator.flatMap(f).nextOption()


5 commentaires

myseq.flatmap (f). Thead


@Bogdanvakulenko ces éléments calculeront-ils même après avoir trouvé le premier résultat isdefinefinine ? Si oui, ce serait trop inefficace.


Il le fera, mais vous pouvez utiliser Itérateur pour l'empêcher comme vous l'avez fait: mysq.itéatator.flatmap (f). Thead


ou convertir en flux: mysq.to stream.flatmap (f). Thead


Ou vous pouvez simplement utiliser une collection paresseuse pour mysq , vous n'avez donc pas à le convertir partout. Il peut être: flux (lazyliste), itérateur ou vue


4 Réponses :


-1
votes

Vous n'avez pas besoin de l'itérateur du tout que vous pouvez simplement faire

mysq.find (f (_). ISDEfinefin)

Voici un test qui montre que trouver fonctionne immédiatement sans itérateur (heure est en microsecondes) xxx

résultat Xxx


8 commentaires

Quoi??? Si le tout premier résultat est un aucun alors je ne le veux pas. Pourquoi devrais-je appeler .head dessus? Dans tous les cas, si cela calcule des éléments même après avoir trouvé le premier résultat non défini, il serait trop inefficace à mes besoins.


Je pensais que j'étais assez clair mais je suppose que non, j'ai donc révisé la réponse. Cela a-t-il aidé?


Afray Not - 1) Votre Head doit être un Heoption de toute façon et 2) Je ne veux que le premier résultat calculé et court-circuité.


Eh bien, j'étais un peu confus par le libellé de votre question, je suppose que c'est mieux maintenant que vous l'avez édité. Quoi qu'il en soit, je ferais cela avec la correspondance des motifs, donc j'ai fait un exemple rapide pour vous dans la réponse révisée.


Vous n'avez toujours pas besoin d'un homme itérateur que vous pouvez simplement mysq.find (f (_)! = Aucun)


Non, cela retournera les éléments de la séquence et non le résultat de l'application de f. Maintenant, vous devrez recompagner l'application de f.


Vous pouvez simplement mapper la fonction à nouveau man que la complexité d'exécution moyenne n'est toujours pas O (n) mysq.find (f (_). ISDEFINÉ) .MAP (F)


Look "homme", je ne veux pas calculer f deux fois si je n'ai pas besoin.



1
votes

mysq.itéator.flatmap (a => f (a)). Toseq.HeadOption

Malheureusement, .toseq doit être appelé depuis itérateur n'a pas case méthode.

mais toseq renvoie flux pour itérateur qui est éventuellement évalué afin que des calculs inutiles ne se produisent pas. <- seulement avant SCALA 2.13


3 commentaires

DEF TRYPICK [A, B] (F: A => OPTION [B]) (myseq: SEQ [A]) = mysq.ativeatorator.flatmap (f). Cadhoption ne compile pas. Comment puis-je le faire compiler?


myseq.itéatator.flatmap (f) .nextoption sur scala 2.13


Je ne compterais pas sur toseq pour renvoyer un flux . Par exemple. Sur 2.13, il renvoie une liste .



2
votes

Vous pouvez également l'implémenter vous-même:

scala> def myFn(int: Int) = if (int > 2) Some(int) else None
myFn: (int: Int)Option[Int]

scala> tryPick(myFn, List(1, 0, -2, 3))
res0: Option[Int] = Some(3)


1 commentaires

Merci. Je cherchais efficacement plus plus d'idiomatique; Je vais probablement coller à ma solution d'origine pour l'instant. Upvoted.



2
votes

trypick est presque équivalent à CollectFirst . Sauf que collectFirst fonctionne avec un partialfunction . Donc, le plus proche que vous obtiendrez est probablement: xxx

voir: xxx


0 commentaires