define a map over boolean scala - scala

I am trying to change the value of an array based on the value of a different array. In particular these are the arrays I am working with:
val inpoly: Array[Boolean]=Array(false, true, true, false)
val idx1: Array[Boolean]=Array(true, false, false, false)
I would like to check the array idx1 and where it is true I would like to assign to a new vector the opposite value of the array inpoly in that specific position, otherwise, just leave the value that inpoly already has.
My expectation would be to have this array:
final_vector= true, true, true, false
since the first value of idx1 is true, change the first value of inpoly. All the other values of idx1 are false, so leave the inpoly as it is
I tried with the following code:
idx1.map({
case true => !inpoly
case false => inpoly}
)
However i get the following error:
<console>:73: error: value unary_! is not a member of Array[Boolean]
case true => !inpoly
^
Can anyone help?

You are doing an element-by-element comparison of two collections. The best way to do this is to zip them together and then map the two values to give the answer:
inpoly.zip(idx1).map{ case (poly, idx) => poly ^ idx }
In this case the two values are xor-ed, but clearly you can use any combination of the two values to generate the result.

Related

Check if element wise condition in Scala list

I would like to get a list such as
val mask = List(true, false, false, false, false)
when evaluating elementwise if an element is equal to "DoubleType"
val column_type = List("DoubleType", "LongType", "LongType", "LongType", "StringType")
I got something similar when using
val mask = new ListBuffer[String]()
for (name <- column_type)
mask += (name == "DoubleType").toString
But you can see that I had to turn every element into a string, otherwise I get an error. And this way I can't use it later as a mask.
What should I do? Any more scalastic way of solving this issue?
You can use .map with a predicate
val mask = column_type.map(_ == "DoubleType")
val mask=column_type.map(a=>a.equals("DoubleType"))
The most concise way to accomplish your goal is via map:
scala> val mask = column_type.map(_ == "DoubleType")
mask: List[Boolean] = List(true, false, false, false, false)
Scala has a rich suite of tools for operating on collections, see https://docs.scala-lang.org/overviews/scala-book/collections-methods.html for more details.

Apply function to all elements of a WrappedArray elegantly

This:
val checkValue = udf { (array: WrappedArray[String], value: String) => array.contains(value) }
works if you do not worry about case of words.
I can apply .toLowerCase() to value easily enough to get this ...(value.toLowerCase() )
But how to apply to the incoming array being WrappedArray and not externally?
array.contains(value)
is the same as
array.exists(_ == value)
The _ == value can be replaced by an arbitrary predicate.
In your case, it would be something like
array.exists(value.equalsIgnoreCase)
Also, note that "ß".toUpperCase == "SS" is true, whereas "ß" == "SS".toLowerCase and "ß".compareIgnoreCase("SS") are both false, see for example this answer.

How to filter on a Option[Boolean] column in slick

I have the following column in my db, thats a Boolean, but also accepts NULL, so true, false, and NULL are all valid:
def rtb = column[Option[Boolean]]("rtb")
and have the following optional input from the client that I'd like to filter on:
rtbFromClient: Option[Boolean] = ...
I have the following (based on this answer on how to do queries in slick: https://stackoverflow.com/a/40888918/5300930):
val query = userTable.
filter(row =>
if (rtbFromClient.isDefined)
row.rtb.get === rtbFromClient.get
else
LiteralColumn(true)
)
but am getting this error when the code runs:
Caught exception while computing default value for Rep[Option[_]].getOrElse -- This cannot be done lazily when the value is needed on the database side
I thought it may be because row.rtb.get was throwing exception on call to get because the value in the db was null, so tried changing it to row.rtb.getOrElse(null) and row.rtb.getOrElse(None) but neither of these worked either)
Also tried the following:
if (rtbFromClient.isDefined) {
val query = query.filter(_.rtb.isDefined).filter(_.rtb.get === rtbFromClient.get)
}
But this also throws the same error at runtime:
Caught exception while computing default value for Rep[Option[_]].getOrElse -- This cannot be done lazily when the value is needed on the database side
To summarise:
I have an Option[Boolean] column in my db that can contain true, false or NULL (the actual mysql type is a tinyint(1), which is mapped to a slick Option[Boolean])
I have an optional filter provided by the user, rtbFromClient that I'd like to filter on if present. If present, this will be either true or false
I have other optional filters (not shown here) that have similar behavior so I'd like to be able to combine them easily
I had the same issue. My solution is (tested with Slick 3.3.x):
val query = usersTable.filterOpt(rtbFromClient)(_.rtb === _)
Situation 1 (when rtbFromClient is empty) corresponds the following SQL:
select * from users;
Situation 2 (rtbFromClient is defined):
select * from users where rtb = ?;
Fist check if the column is null and then go ahead with another comparison. Ensure that rtbFromClient is not an option.
val query = userTable.filter(row => !row.rtb.isEmpty &&
row.rtb === rtbFromClient)
The first condition ensures that nulls are filtered and the second condition checks the value in case the column value is not null.
In case you have optional value, then below code helps.
def query(value: Option[Boolean]) = value match {
case Some(userGivenRtbFromClient) =>
userTable.filter(row => !row.rtbFromClient.isNull &&
row.rtbFromClient === userGivenRtbFromClient)
case None => userTable.filter(row => row.rtbFromClient.isNull)
}
The Much cleaner version is here.
rtbFromClient: Option[Boolean]
rtbFromClient User given optional value to compare with slick column.
userTable.filter(row => rtbFromClient.map(value => row.rtb === Some(value): Option[Boolean]).getOrElse(row.rtb.isEmpty))
var query = userTable.drop(page.skip).take(page.top)
if (rtbFromClient.isDefined) {
query = query.filter(row => row.rtb.isDefined && row.rtb === rtbFromClient)
}
// More if blocks with optional filters here
...
dbProvider.db.run(query.result)
try this
val query = userTable.filter(row => rtbFromClient.map(x => Option(x) === row.rtb).getOrElse(row.rtb.isEmpty.?))
I was facing the same issue. After playing around I realised one can filter by the option directly, so if we have the column
def rtb = column[Option[Boolean]]("rtb")
and we're trying to filter by
rtbFromClient: Option[Boolean] = ...
then we can do:
val query: DBIO[Seq[TableElementType]] =
if (rtbFromClient.isDefined)
userTable.filter(_.rtb === rtbFromClient).result
else
userTable.result

Build a List of Arrays recursively in Scala

I am newbie to Scala and I am trying to build a list of arrays recursively in scala, here is the code I have, it is not throwing any error when I run it, but, its not printing anything when I try unCons.foreach(println)
val Tot = 5
val Num = 5
var unCons = ListBuffer[String]()
for(j <- 1 to Tot)
{
var OurArr = ListBuffer[String]()
for(i <- 1 to Num)
{
OurArr:+("true")
}
unCons:+(OurArr.toList)
}
The result I am expecting is something like this
[[true, true, true, true, true],
[true, true, true, true, true],
[true, true, true, true, true],
[true, true, true, true, true],
[true, true, true, true, true]]
Any idea, where I am going wrong?
The "Scala way" might be to use List.fill
scala> List.fill(5)(List.fill(5)(true))
res0: List[List[Boolean]] = List(List(true, true, true, true, true), List(true, true, true, true, true), List(true, true, true, true, true), List(true, true, true, true, true), List(true, true, true, true, true))
You've got a number of issues going on.
First you're not properly assigning to the ListBuffer.
OurArr :+= "true"
Next you're unCons is the wrong type for what you're trying to do.
var unCons = ListBuffer[List[String]]()
After these fixes you'll want to look into good Scala practice, like avoiding the use of var whenever possible (and it is almost always possible).
One other thing: there's no recursion in this code. If you're trying to build a list recursively (as the question title suggests) then you need a completely different approach.
Any idea, where I am going wrong?
There are three errors you are making:
unCons is of type ListBuffer[String]. OurArr is also of type ListBuffer[String]. You are trying to add the collection OurArr to unCons which will give you a type mismatch error. unCons only accepts elements of a type String while you are trying to add elements of type ListBuffer[String] to it. So, first make your unCons of type ListBuffer[ListBuffer[String]] so that it can accept elements of type OurArr
You are using the :+ method to append elements to your OurArr collection OurArr:+("true"), which returns a new collection instead of editing that collection in place.
From the scaladoc:
def +:(elem: A): ListBuffer[A]
A copy of the list buffer with an element prepended.
In your case, you should use OurArr += ("true") which edits your collection in place and does not return a new collection.
You would guess that operations on mutable collections would return the same collection after operations. But that is NOT the case. Many operations on mutable collections return a new copy of the collection and you will need to capture that new collection.
This line: unCons:+(OurArr.toList) is causing the same issue as #2 above. The :+ operator is returning a new collection and you are not capturing that collection in a variable. Instead, you could use unCons += OurArr to edit the collection in place.
Last but not the least, you should AVOID VARS as far as possible in Scala. You will be surprised that you rarely ever need to use a var in Scala. For example, in your case: you used two vars:
var unCons = ListBuffer[String]()
var OurArr = ListBuffer[String]()
Both of them can be val's with no change on your code's behavior. Remember, when you declare an object as a val it does NOT mean you can'S change/edit the content of the object. THE only difference is that you can't change the pointer to point to some different memory address. So, in both your cases you can safely use vals:
So your code becomes:
val Tot = 5
val Num = 5
val unCons = ListBuffer[ListBuffer[String]]()
for(j <- 1 to Tot)
{
val OurArr = ListBuffer[String]()
for(i <- 1 to Num)
{
OurArr += ("true")
}
unCons += OurArr
}

Taking the Vector out of Some

In my code, after an API call, I am getting
Some(Vector(72981, 72982)).
I need to get the vector out of Some so that I modify the vector. Tried many things but no result.
Using map you can modify what's in the Option (i.e. the Some in this case)
Some(Vector(72981, 72982)).map(vector => // do something with vector)
// Some(modifiedVector)
this will return the modified vector inside an Option.
If you want to extract the value from the Option, you can use getOrElse
val v = Some(Vector(72981, 72982)).getOrElse(/* a fallback value */)
or a match
val opt = Some(Vector(72981, 72982))
opt match {
case Some(vector) => // do something with vector
case None => // vector doesn't exist
}