Scala Matching Pattern

Trying to get a pattern matching descriptor here - based on the C ++ / Java background, is very foreign to me.

The point of this branch is to check each member of the list of d tuples [format (string, object). I want to identify three cases.

1) If the counter in this function is larger than the list size (defined in another called acc), I want to return nothing (because there is no match) 2) If the key specified in the input file matches the tuple in the list, I want to return its value ( or, whatever is stored in tuple._2). 3) If there is no match, and there is even more list for iteration, increase and continuation.

My code is below:

 def get(key:String):Option[Any] = { var counter: Int = 0 val flag: Boolean = false x match { case (counter > acc) => None case ((d(counter)._1) == key) => d(counter)._2 case _ => counter += 1 } 

My problem here is when the first case seems to compile correctly, the second causes an error:

  : 36: error: ')' expected but '.'  found.
                 case ((d (counter) ._ 1) == key) => d (counter) ._ 2 

Third:

  scala> case _ => counter + = 1
 : 1: error: illegal start of definition 

But I guess this is because the second is wrong. My first thought is that I am not matching the tuples correctly, but it seems that I am following the indexing syntax in the tuple, so I'm at a dead end. Can someone direct me in the right direction?

+4
source share
3 answers

Hope a few things to eliminate your confusion:

Compliance in scala follows a common pattern:

 x match { case SomethingThatXIs if(SomeCondition) => SomeExpression // rinse and repeat // note that `if(SomeCondition)` is optional } 

It looks like you might have tried to use the match / case expression as more of the if / else if / else block, and as far as I can tell, x doesn't really matter within the specified block. If that happens, you might be fine with something like

 case _ if (d(counter)._1 == key) => d(counter)._2 

BUT

Some information about List in scala. You should always think of it as a LinkedList , where an indexed search is an O(n) operation. Lists can be mapped to head :: tail , and Nil can be an empty list. For instance:

 val myList = List(1,2,3,4) myList match { case first :: theRest => // first is 1, theRest is List(2,3,4), which you can also express as // 2 :: 3 :: 4 :: Nil case Nil => // an empty list case } 

It looks like you are creating a kind of ListMap, so I will write a more "functional" / "recursive" way to implement your get method.

I assume d is a support list of type List[(String, Any)]

 def get(key: String): Option[Any] = { def recurse(key: String, list: List[(String, Any)]): Option[Any] = list match { case (k, value) :: _ if (key == k) => Some(value) case _ :: theRest => recurse(key, theRest) case Nil => None } recurse(key, d) } 

Three cases can be explained as follows:

1) The first element in a List is a collection of (k, value) . The rest of the list matches _ , because in this case we do not care about that. The condition asks if k key we are looking for. In this case, we want to return value from the tuple.

2) Since the first element did not have the correct key, we want to return it. We do not care about the first element, but we need the rest of the list so that we can rewrite it.

3) case Nil means that there is nothing in the list, which should mean "failure" and the end of the recursion. In this case, we return None . Consider this the same as your counter > acc clause from your question.

Please feel free to contact for further clarification; and if I accidentally made a mistake (I don’t compile, etc.), indicate this and I will fix it.

+6
source

I assume that conditionally extracting part of a tuple from the list of tuples is an important part of your question, sorry if I'm wrong.

First, the starting point, in Scala we will usually use AnyRef instead of Object, or if it is, we will use a type parameter that can increase the reuse of a function or method and increase type safety.

The three cases you described can be minimized in two cases: the first case uses protection (the if statement after matching the pattern), the second case matches the entire non-empty list and looks for a match between each first tuple argument and key, returning Some [T] containing the second argument of the tuple the corresponding tuple or None if a match does not occur. The third case is not required because the search operation crosses (iterates) the list.

The map operation after the search is used to extract the second argument of the tuple (the map on Option returns a parameter), delete this operation and change the type of the returned method to Option [(String, T)] if you want the whole Tuple to return.

 def f[T](key: String, xs: List[(String, T)], initialCount: Int = 2): Option[T] = { var counter = initialCount xs match { case l: List[(String, T)] if l.size < counter => None case l: List[(String, T)] => l find {_._1 == key} map {_._2} } } f("A", List(("A", 1), ("B", 2))) // Returns Some(1) f("B", List(("A", 1), ("B", 2))) // Returns Some(2) f("A", List(("A", 1))) // Returns None f("C", List(("A", 1), ("B", 2))) // Returns None f("C", Nil) // Returns None 
+2
source

First, why are you using List for this reason? You definitely need a Map . Its get() returns None if the key is not found, and Some(value) if it is found in it.

Secondly, what is x in your example? Is this a list?

Thirdly, you cannot write case (log) => .. , where log is a logical condition, it is in the form case _ if (log) => ... (as Rex Kerr has already crossed out in his comment).

Fouth, you need a recursive function for this (just increasing the counter will only cause this on the second element).

So you will need something similar (if you prefer to stick with List ):

 def get(l: List[Tuple2[String, String]], key: String): Option[String] = { if (l.isEmpty) { None } else { val act = l.head act match { case x if (act._1 == key) => Some(act._2) case _ => get(l.tail, key) } } } 
0
source

Source: https://habr.com/ru/post/1435119/


All Articles