Max Pagels
Max Pagels

Reputation:

Returning an element from a List in Scala

I've recently been working on a beginner's project in Scala, and have a beginner question about Scala's Lists.

Say I have a list of tuples ( List[Tuple2[String, String]], for example). Is there a convenience method to return the first occurence of a specified tuple from the List, or is it necessary to iterate through the list by hand?

Upvotes: 17

Views: 27924

Answers (7)

elm
elm

Reputation: 20435

Consider collectFirst which delivers Some[(String,String)] for the first matching tuple or None otherwise, for instance as follows,

xs collectFirst { case t@(a,_) if a == "existing" => t }
Some((existing,str))

scala> xs collectFirst { case t@(a,_) if a == "nonExisting" => t }
None

Using @ we bind the value of the tuple to t so that a whole matching tuple can be collected.

Upvotes: 1

Tim Sullivan
Tim Sullivan

Reputation: 16898

You could try using find. (Updated scala-doc location of find)

Upvotes: 6

akauppi
akauppi

Reputation: 18076

Here's code that may help you.

I had a similar case, having a collection of base class entries (here, A) out of which I wanted to find a certain derived class's node, if any (here, B).

class A

case class B(val name: String) extends A

object TestX extends App {
  val states: List[A] = List( B("aa"), new A, B("ccc") )

  def findByName( name: String ): Option[B] = {
    states.find{
      case x: B if x.name == name => return Some(x)
      case _ => false
    }
    None
  }

  println( findByName("ccc") )    // "Some(B(ccc))"
}

The important part here (for my app) is that findByName does not return Option[A] but Option[B].

You can easily modify the behaviour to return B instead, and throw an exception if none was found. Hope this helps.

Upvotes: 1

sblundy
sblundy

Reputation: 61434

If you're learning scala, I'd take a good look at the Seq trait. It provides the basis for much of scala's functional goodness.

Upvotes: 2

Alex Cruise
Alex Cruise

Reputation:

You could also do this, which doesn't require knowing the field names in the Tuple2 class--it uses pattern matching instead:

list find { case (x,y,_) => x == "C" && y == "D" }

"find" is good when you know you only need one; if you want to find all matching elements you could either use "filter" or the equivalent sugary for comprehension:

for ( (x,y,z) <- list if x == "C" && y == "D") yield (x,y,z)

Upvotes: 1

Daniel Spiewak
Daniel Spiewak

Reputation: 55123

As mentioned in a previous comment, find is probably the easiest way to do this. There are actually three different "linear search" methods in Scala's collections, each returning a slightly different value. Which one you use depends upon what you need the data for. For example, do you need an index, or do you just need a boolean true/false?

Upvotes: 3

Binil Thomas
Binil Thomas

Reputation: 13809

scala> val list = List(("A", "B", 1), ("C", "D", 1), ("E", "F", 1), ("C", "D", 2), ("G", "H", 1))
list: List[(java.lang.String, java.lang.String, Int)] = List((A,B,1), (C,D,1), (E,F,1), (C,D,2), (G,H,1))

scala> list find {e => e._1 == "C" && e._2 == "D"}
res0: Option[(java.lang.String, java.lang.String, Int)] = Some((C,D,1))

Upvotes: 13

Related Questions