if i have
scala> test
res3: Array[java.io.Serializable] = Array(Array((AA,BB), (CC,DD)), (EE,FF))
and i want to convert this to
Array[(Any, Any)] = Array((AA,BB), (CC,DD), (EE,FF))
I can convert using flatMap function like this
scala> val test2 = test.flatMap{
| case (a,b) => Array((a,b))
| case i:Array[Any] => i.flatMap{
| case (a,b)=> Array((a,b))}
| }
test2: Array[(Any, Any)] = Array((AA,BB), (CC,DD), (EE,FF))
but I want to make function for All depth of Arrays.
so I tried
scala> def flatArray(array: Array[Any]): Array[(Any,Any)] ={
| array.flatMap{
| case (a,b) => Array((a,b))
| case i:Array[Any] => flatArray(i)
| }
| }
scala> val test2 = flatArray(test)
<console>:9: error: type mismatch;
found : Array[java.io.Serializable]
required: Array[Any]
Note: java.io.Serializable <: Any, but class Array is invariant in type T.
You may wish to investigate a wildcard type such as `_ <: Any`. (SLS 3.2.10)
val test2 = flatArray(test)
^
what's the problem ???
You can do flattening the following way:
def flatten(arr:Array[Any]):Array[(Any,Any)] =
arr.flatMap {
case (a,b) => Array((a,b))
case v:Array[Any] => flatten(v)
}
Well, I have a solution, maybe not the best one, since it uses non-tail recursion that may lead to a problems when you have a lot of data. Also, it assumes, that you don't have mixed tuples and arrays on the same level (like Array(1 -> 2, Array(2 -> 3)). So, just for reference:
import scala.collection.mutable.ArrayBuffer
val a: Array[Any] =
Array(
Array(1 -> 2, 2 -> 3),
Array(
Array(7 -> 1, 8 -> 3),
Array(
Array(1 -> 4, 5 -> 6, 12 -> 5),
Array(3 -> 4)
)
)
)
def flattenImpl(arr: Array[Any], acc: ArrayBuffer[(Int, Int)]): Array[(Int, Int)] = {
arr.headOption match {
case None => acc.toArray
case Some((a: Int, b:Int)) => flattenImpl(arr.tail, acc :+ a -> b)
case Some(a: Array[Any]) => flattenImpl(a, acc ++ flattenImpl(arr.tail, acc))
}
}
def flatten(arr: Array[Any]): Array[(Int, Int)] = flattenImpl(arr, ArrayBuffer())
val res = flatten(a)
res: Array[(Int, Int)] = Array((3,4), (1,4), (5,6), (12,5), (7,1), (8,3), (1,2), (2,3))
Related
I want to write a simple method that takes a function as a parameter and then executes it.
def exec(f: (a:Int, b:Int) => Boolean): Boolean = f(a,b)
I'm not sure what is wrong with the above, but I get the error:
<console>:1: error: ')' expected but ':' found.
def exec(f: (a:Int, b:Int) => Boolean): Boolean = f(a,b)
^ ^
| |
// These are supposed to be types, but a: Int and b: Int aren't types,
// they are identifiers with type ascriptions.
It should look a little more like:
def exec(f: (Int, Int) => Boolean): Boolean = f(a, b)
Now f is a function (Int, Int) => Boolean. But this doesn't compile, because a and b are not defined.
You either need to pass them in, or fix them to a value.
def exec(a: Int, b: Int)(f: (Int, Int) => Boolean): Boolean = f(a, b)
scala> exec(2, 3)(_ > _)
res1: Boolean = false
If you want to execute a function with parameters in your exec method you need to:
scala> def exec(f: => Unit) = {
| println("Exec:")
| f
| }
scala> def foo(f : (Int, Int)): Unit = println(f._1 + f._2)
scala> exec(foo((3, 4)))
Exec:
7
because foo((3, 4)) type is => Unit
Not quite an answer to your original question (and too big to be a comment), but if you're looking to write a tasteful, nice-looking execution operator and don't particularly like the syntax of the provided answers, perhaps something similar to scalaz's pipe operator (|>) might be what you're thinking of?
scala> // You could just get this from scalaz with import scalaz._ and import Scalaz._
scala> implicit class FancyExec[A](x: A){def |>[B](f: A => B) = f(x)}
scala> 5 |> (_ + 6)
res1: Int = 11
scala> (5, 4) |> ((_: Int) < (_: Int)).tupled
res2: Boolean = false
scala> val f = ((_: Int) < (_: Int)).tupled
f: ((Int, Int)) => Boolean = <function1>
scala> val g = ((_: Int) > (_: Int)).tupled
g: ((Int, Int)) => Boolean = <function1>
scala> List(f, g) map ((5, 4) |> _)
res3: List[Boolean] = List(false, true)
Consider a flatMap written over some case matching. For example:
list.flatMap( v =>
v match {
case Cond1 => if(something) Some(Int) else None
//..Other conditions yielding Option[Int]
case CondN => if(somethingelse) Seq(Int) else Seq()
})
However this wont compile. If the seq is all of Option[Int] or all of Seq[Int] the flatMap works. But not if the Seq is a mix of Options and Seqs. Why is such a restriction in place? Does this solve a particular ambiguity that I cannot think of as of now.
EDIT1
Adding code snippet from REPL
scala> val a = Seq(Option(1), Seq(2,3))
a: Seq[Equals] = List(Some(1), List(2, 3))
scala> val b = Seq(Seq(1), Seq(2,3))
b: Seq[Seq[Int]] = List(List(1), List(2, 3))
scala> a.flatMap(x=>x)
<console>:9: error: type mismatch;
found : Equals
required: scala.collection.GenTraversableOnce[?]
a.flatMap(x=>x)
^
scala> b.flatMap(x=>x)
res24: Seq[Int] = List(1, 2, 3)
EDIT2
After Filippo's answer I tried the following piece of code in the REPL and it worked.
scala> val options = Seq("opt1", "opt2")
options: Seq[String] = List(opt1, opt2)
scala> options.flatMap( x =>
| x match {
| case "opt1" => Some(1)
| case "opt2" => Seq(2,3)
| case _ => None
| })
res27: Seq[Int] = List(1, 2, 3)
How is the resolution different in each of the scenarios.
More importantly when I map instead of flatMap the result is the same as the Seq a that I had created.
scala> options.map( x =>
| x match {
| case "opt1" => Some(1)
| case "opt2" => Seq(2,3)
| case _ => None
| })
res28: Seq[Equals] = List(Some(1), List(2, 3))
Option is a GenTraversableOnce but scala needs some help here:
val a: Seq[TraversableOnce[Int]] = Seq(Option(1), Seq(2,3))
a.flatMap(x=>x)
res0: Seq[Int] = List(1, 2, 3)
EDIT after additions to the question
I think that if the type of your sequence is the one you are expecting, everything boils down to the function passed to the flatMap. If scala can't figure out that the function is (A) => Traversable[A] when the starting sequence is Seq[A], I think we should make some types explicit.
Now, back to your first sample, I would refactor it as:
list.flatMap {
case Cond1 if something => Seq(Int)
case CondN if somethingelse => Seq(Int)
case _ => Seq()
}
No doubt scala is now able to infer the types correctly.
So I have an expensive method with this signature
def func(param: Int): \/[String, Int]
I am trying to loop over a list of params and returns \/[String, List[Int]] but stop the loop whenever the method returns -\/.
I come up with this:
scala> def func(i: Int) = {
| if( i > 1 ) { println{"!!"} ;"error".left[Int]}
| else i.right[String]
| }
func: (i: Int)scalaz.\/[String,Int]
scala> val toList = (dis: scalaz.\/[String,Int]) => {dis.map(i => List(i))}
toList: scalaz.\/[String,Int] => scalaz.\/[String,List[Int]] = <function1>
scala> val composed = (func _) andThen toList
composed: Int => scalaz.\/[String,List[Int]] = <function1>
scala> (1 to 3).toList.foldLeftM(List[Int]().right[String]){(dis, i) =>
| for{
| a <- dis
| b <- composed(i)
| } yield a |+| b
| }
<console>:17: error: no type parameters for method foldLeftM: (f: (scalaz.\/[String,List[Int]], Int) => G[scalaz.\/[String,List[Int]]])(implicit M: scalaz.Monad[G])G[scalaz.\/[String,List[Int]]] exist so that it can be applied to arguments ((scalaz.\/[String,List[Int]], Int) => scalaz.\/[String,List[Int]])
--- because ---
argument expression's type is not compatible with formal parameter type;
found : (scalaz.\/[String,List[Int]], Int) => scalaz.\/[String,List[Int]]
required: (scalaz.\/[String,List[Int]], Int) => ?G[scalaz.\/[String,List[Int]]]
(1 to 2).toList.foldLeftM(List[Int]().right[String]){(dis, i) =>
^
<console>:17: error: type mismatch;
found : (scalaz.\/[String,List[Int]], Int) => scalaz.\/[String,List[Int]]
required: (scalaz.\/[String,List[Int]], Int) => G[scalaz.\/[String,List[Int]]]
(1 to 2).toList.foldLeftM(List[Int]().right[String]){(dis, i) =>
^
What's the G[_] here and what's the correct result type in foldLeftM ?
Solved by noted two mistake I made:
misunderstood about type of initial/carried over value, it should be List[Int] instead of \/
one has to explicit declare type parameter of foldLeftM
scala> def func(i: Int) = {
| if( i > 1 ) { println{"!!"} ;"error".left[Int]}
| else i.right[String]
| }
func: (i: Int)scalaz.\/[String,Int]
scala> val toList = (dis: scalaz.\/[String,Int]) => {dis.map(i => List(i))}
toList: scalaz.\/[String,Int] => scalaz.\/[String,List[Int]] = <function1>
scala> val composed = (func _) andThen toList
composed: Int => scalaz.\/[String,List[Int]] = <function1>
scala> val f = (dis: List[Int], i: Int) => composed(i).map(r => dis |+| r)
f: (List[Int], Int) => scalaz.\/[String,List[Int]] = <function2>
scala> (1 to 4).toList.foldLeftM[({type l[a] = String \/ a})#l, List[Int]](List[Int]())(f)
!!
res16: scalaz.\/[String,List[Int]] = -\/(error)
I have a nested tuple structure like (String,(String,Double)) and I want to transform it to (String,String,Double). I have various kinds of nested tuple, and I don't want to transform each manually. Is there any convenient way to do that?
If you use shapeless, this is exactly what you need, I think.
There is no flatten on a Tupple. But if you know the structure, you can do something like this:
implicit def flatten1[A, B, C](t: ((A, B), C)): (A, B, C) = (t._1._1, t._1._2, t._2)
implicit def flatten2[A, B, C](t: (A, (B, C))): (A, B, C) = (t._1, t._2._1, t._2._2)
This will flatten Tupple with any types. You can also add the implicit keyword to the definition. This works only for three elements. You can flatten Tupple like:
(1, ("hello", 42.0)) => (1, "hello", 42.0)
(("test", 3.7f), "hi") => ("test", 3.7f, "hi")
Multiple nested Tupple cannot be flatten to the ground, because there are only three elements in the return type:
((1, (2, 3)),4) => (1, (2, 3), 4)
Not sure about the effiency of this, but you can convert Tuple to List with tuple.productIterator.toList, then flatten the nested lists:
scala> val tuple = ("top", ("nested", 42.0))
tuple: (String, (String, Double)) = (top,(nested,42.0))
scala> tuple.productIterator.map({
| case (item: Product) => item.productIterator.toList
| case (item: Any) => List(item)
| }).toList.flatten
res0: List[Any] = List(top, nested, 42.0)
Complement of answer above
Paste this utility code:
import shapeless._
import ops.tuple.FlatMapper
import syntax.std.tuple._
trait LowPriorityFlatten extends Poly1 {
implicit def default[T] = at[T](Tuple1(_))
}
object flatten extends LowPriorityFlatten {
implicit def caseTuple[P <: Product](implicit lfm: Lazy[FlatMapper[P, flatten.type]]) =
at[P](lfm.value(_))
}
then you are able to flatten any nested tuple:
scala> val a = flatten(((1,2),((3,4),(5,(6,(7,8))))))
a: (Int, Int, Int, Int, Int, Int, Int, Int) = (1,2,3,4,5,6,7,8)
Note that this solution does not work for self-defined case class type, which would be converted to String in the output.
scala> val b = flatten(((Cat("c"), Dog("d")), Cat("c")))
b: (String, String, String) = (c,d,c)
In my opinion simple pattern matching would work
scala> val motto = (("dog", "food"), "tastes good")
val motto: ((String, String), String) = ((dog,food),tastes good)
scala> motto match {
| case ((it, really), does) => (it, really, does)
| }
val res0: (String, String, String) = (dog,food,tastes good)
Or if you have a collection of such tuples:
scala> val motto = List(
| (("dog", "food"), "tastes good")) :+ (("cat", "food"), "tastes bad")
val motto: List[((String, String), String)] = List(((dog,food),tastes good), ((cat,food),tastes bad))
scala> motto.map {
| case ((one, two), three) => (one, two, three)
| }
val res2: List[(String, String, String)] = List((dog,food,tastes good), (cat,food,tastes bad))
I think it would be convenient even if you have several cases.
I have some financial data gathered at a List[(Int, Double)], like this:
val snp = List((2001, -13.0), (2002, -23.4))
With this, I wrote a formula that would transform the list, through map, into another list (to demonstrate investment grade life insurance), where losses below 0 are converted to 0, and gains above 15 are converted to 15, like this:
case class EiulLimits(lower:Double, upper:Double)
def eiul(xs: Seq[(Int, Double)], limits:EiulLimits): Seq[(Int, Double)] = {
xs.map(item => (item._1,
if (item._2 < limits.lower) limits.lower
else if (item._2 > limits.upper) limits.upper
else item._2
}
Is there anyway to extract the tuple's values inside this, so I don't have to use the clunky _1 and _2 notation?
List((1,2),(3,4)).map { case (a,b) => ... }
The case keyword invokes the pattern matching/unapply logic.
Note the use of curly braces instead of parens after map
And a slower but shorter quick rewrite of your code:
case class EiulLimits(lower: Double, upper: Double) {
def apply(x: Double) = List(x, lower, upper).sorted.apply(1)
}
def eiul(xs: Seq[(Int, Double)], limits: EiulLimits) = {
xs.map { case (a,b) => (a, limits(b)) }
}
Usage:
scala> eiul(List((1, 1.), (3, 3.), (4, 4.), (9, 9.)), EiulLimits(3., 7.))
res7: Seq[(Int, Double)] = List((1,3.0), (3,3.0), (4,4.0), (7,7.0), (9,7.0))
scala> val snp = List((2001, -13.0), (2002, -23.4))
snp: List[(Int, Double)] = List((2001,-13.0), (2002,-23.4))
scala> snp.map {case (_, x) => x}
res2: List[Double] = List(-13.0, -23.4)
scala> snp.map {case (x, _) => x}
res3: List[Int] = List(2001, 2002)