Ternary operator usage in Scala program [closed]

2020-04-01 08:37发布

问题:


Want to improve this question? Update the question so it's on-topic for Stack Overflow.

Closed 3 years ago.

I have a Array of Objects that I need to apply filter.

val filteredList = list.filter{ l =>  (pid == "") ? true : l.ProviderId.toUpperCase().contains(pid.toUpperCase()))}

This code is not getting complied by Scala compiler. I am getting error like 1) value ? is not a member of boolean 2) type toUpperCase is not a member of string.

Can anyone please help me how to write this ternary operator inside the filter function in scala.

I agree that I can write a custom function to handle this as mentioned @ Ternary Operators in Scala However, I am interested in why there is compilation error for this statement. Because, this is valid statement in Java.

回答1:

The main issue is that Scala does not support the ternary operator you described. That is supported Java but there's no need for it in Scala.

In Java the main difference between the if statement and the ternary operator is that the latter is an expression, meaning that it's evaluated to a result, while if is (as I previously suggested) a statement that relies on side-effects within its scope to make things happen.

In Scala if is already an expression, hence there is no need for a ternary operator.

Your code would be structured as follows:

val filteredList = list.filter { l => if (pid == "") true else l.ProviderId.toUpperCase().contains(pid.toUpperCase()) }

As suggested in a comment you can further improve the readability by not relying on ifs to express simple boolean conditions.

val filteredList = list.filter { l => pid == "" || l.ProviderId.toUpperCase().contains(pid.toUpperCase())) }

Furthermore, in your case, pid seems to be external to the list itself, so maybe pulling it out of the filter (which has O(n) complexity on List) can save you some cycles:

val filteredList = if (pid.isEmpty) list else list.filter(_.ProviderId.toUpperCase().contains(pid.toUpperCase()))

It also looks like you are trying to make a case-insensive equality check on the two string, in which case you may be interested in using a Pattern and not converting pid to upper case at every loop:

val pidPattern = Pattern.compile(Pattern.quote(pid), Pattern.CASE_INSENSITIVE)

val filteredList = if (pid.isEmpty) list else list.filter(l => pidPattern.matcher(l.ProviderId).find)