Scala 2D array operations on rows from the second item - arrays

Given a 2D array, for instance
val in = Array( Array(10,11,12),
Array(20,21,22))
would like to multiply by 10 each element in each row from the second element on, the first element in each row remains unmodified; the desired outcome in the example would be
val out = Array( Array(10,110,120),
Array(20,210,220))
Many Thanks.

Edited:
val out = in.map {
case Array(head, tail # _*) => head +: tail.toArray.map(_ * 10)
case _ => ...
}
A simplier but a bit unsafe solution:
val out = in.map(arr => arr.head +: arr.tail.map(_ * 10))

val out = in.map(_.zipWithIndex.map {m =>
{ if (m._2==0) m._1 else m._1*10 }
} )
or if you don't like generating the indexes:
val out = in.map (m => (
for {
h <- m.headOption
} yield h +: m.tail.map(_ * 10)
) getOrElse Array())
(both approaches are safe if one of the arrays is empty)

1) This code can throw Exception: java.util.NoSuchElementException: next on empty iterator if one of arrays will empty
in.map(a => {a.head +: a.tail.map(_*10) })
2) more preferable on my mind, but if your array happens to have elements equal to the first one, they won't be multiplied (comment by Alexey Romanov)
in.map(a => a.map(t => if (a.indexOf(t)==0) t else t*10))
3) safe variant of 1)
in.map(a => a.take(1) ++ a.slice(1, a.length).map(_*10))

Related

Process sequence of elements in scala

Given a sorted sequence of pair, I combine the elements if they are continuous or smaller and skip if they are not.
For example:
if A = Seq((1,2),(3,4),(5,6),(8,10)(11,15))
output should be Seq((1,6),(8,15))
since last element of current entry is continuous with first element of next entry
if B = Seq((1,4),(3,5),(6,7),(9,10)(11,15))
output should be Seq((1,7),(9,15))
since last element of current entry is smaller with first element of next entry
I tried something like:
val finalOut = mySeq.sliding(2).map {
case Array(x, y, _*) => (x, y, (x._2 - y._1))
}.toList
The problem with this is it will just take 2 elements at a time, whereas we need to keep traversing unless there is a gap in continuity. I am not sure how to obtain that in scala.
I tried implementing for loop as well, but that also doesn't help, because it processes one element at a time and doesn't help in keeping a track of other elements or counter like c++.
You can do this with foldRight and accumulate into a new Seq.
This works
val tups1 = Seq((1,2),(3,4),(5,6),(8,10),(11,15))
val tups2 = Seq((1,4),(3,5),(6,7),(9,10),(11,15))
def f(tups: Seq[(Int, Int)]): Seq[(Int, Int)] = {
val emptySeq: Seq[(Int, Int)] = Seq()
tups.foldRight(emptySeq){ (next, accum) => accum match {
case Nil => Seq(next)
case (a, b) +: cs if a - 1 <= next._2 => (next._1, next._2 max b) +: cs
case _ => next +: accum
}}
}
f(tups1) // Seq[(Int, Int)] = List((1,6), (8,15))
f(tups2) // Seq[(Int, Int)] = List((1,7), (9,15))
I'd use foldRight over foldLeft because Seq's are Lists under the hood, and for Lists, prepend is constant, while append is O(n), and foldRight lets you accomplish this with only prepends.
https://docs.scala-lang.org/overviews/collections/performance-characteristics.html

How do I take slice from an array position to end of the array?

How do I get an array of array with elements like this? Is there an inbuilt scala api that can provide this value (without using combinations)?
e.g
val inp = Array(1,2,3,4)
Output
Vector(
Vector((1,2), (1,3), (1,4)),
Vector((2,3), (2,4)),
Vector((3,4))
)
My answer is below. I feel that there should be an elegant answer than this in scala.
val inp = Array(1,2,3,4)
val mp = (0 until inp.length - 1).map( x => {
(x + 1 until inp.length).map( y => {
(inp(x),inp(y))
})
})
print(mp)
+Edit
Added combination constraint.
Using combinations(2) and groupBy() on the first element (0) of each combination will give you the values and structure you want. Getting the result as a Vector[Vector]] will require some conversion using toVector
scala> inp.combinations(2).toList.groupBy(a => a(0)).values
res11: Iterable[List[Array[Int]]] = MapLike.DefaultValuesIterable
(
List(Array(2, 3), Array(2, 4)),
List(Array(1, 2), Array(1, 3), Array(1, 4)),
List(Array(3, 4))
)
ORIGINAL ANSWER
Note This answer is OK only if the elements in the Seq are unique and sorted (according to <). See edit for the more general case.
With
val v = a.toVector
and by foregoing combinations, I can choose tuples instead and not have to cast at the end
for (i <- v.init) yield { for (j <- v if i < j) yield (i, j) }
or
v.init.map(i => v.filter(i < _).map((i, _)))
Not sure if there's a performance hit for using init on vector
EDIT
For non-unique elements, we can use the indices
val v = a.toVector.zipWithIndex
for ((i, idx) <- v.init) yield { for ((j, jdx) <- v if idx < jdx) yield (i, j) }

Count elements of array A in array B with Scala

I have two arrays of strings, say
A = ('abc', 'joia', 'abas8', '09ma09', 'oiam0')
and
B = ('gfdg', '89jkjj', '09ma09', 'asda', '45645ghf', 'dgfdg', 'yui345gd', '6456ds', '456dfs3', 'abas8', 'sfgds').
What I want to do is simply to count the number of elements of every string in A that appears in B (if any). For example, the resulted array here should be: C = (0, 0, 1, 1, 0). How can I do that?
try this:
A.map( x => B.count(y => y == x)))
You can do it how idursun suggested, it will work, but may be not efficient as if you'll prepare intersection first. If B is much bigger than A it will give massive speedup. 'intersect' method has better 'big-O' complexity then doing linear search for each element of A in B.
val A = Array("abc", "joia", "abas8", "09ma09", "oiam0")
val B = Array("gfdg", "89jkjj", "09ma09", "asda", "45645ghf", "dgfdg", "yui345gd", "6456ds", "456dfs3", "abas8", "sfgds")
val intersectCounts: Map[String, Int] =
A.intersect(B).map(s => s -> B.count(_ == s)).toMap
val count = A.map(intersectCounts.getOrElse(_, 0))
println(count.toSeq)
Result
(0, 0, 1, 1, 0)
Use a foldLeft construction as the yield off of each element of A:
val A = List("a","b")
val B = List("b","b")
val C = for (a <- A)
yield B.foldLeft(0) { case (totalc : Int, w : String) =>
totalc + (if (w == a) 1 else 0)
}
And the result:
C: List[Int] = List(0, 2)

How to get the element index when mapping an array in Scala?

Let's consider a simple mapping example:
val a = Array("One", "Two", "Three")
val b = a.map(s => myFn(s))
What I need is to use not myFn(s: String): String here, but myFn(s: String, n: Int): String, where n would be the index of s in a. In this particular case myFn would expect the second argument to be 0 for s == "One", 1 for s == "Two" and 2 for s == "Three". How can I achieve this?
Depends whether you want convenience or speed.
Slow:
a.zipWithIndex.map{ case (s,i) => myFn(s,i) }
Faster:
for (i <- a.indices) yield myFn(a(i),i)
{ var i = -1; a.map{ s => i += 1; myFn(s,i) } }
Possibly fastest:
Array.tabulate(a.length){ i => myFn(a(i),i) }
If not, this surely is:
val b = new Array[Whatever](a.length)
var i = 0
while (i < a.length) {
b(i) = myFn(a(i),i)
i += 1
}
(In Scala 2.10.1 with Java 1.6u37, if "possibly fastest" is declared to take 1x time for a trivial string operation (truncation of a long string to a few characters), then "slow" takes 2x longer, "faster" each take 1.3x longer, and "surely" takes only 0.5x the time.)
A general tip: Use .iterator method liberally, to avoid creation of intermediate collections, and thus speed up your computation. (Only when performance requirements demand it. Or else don't.)
scala> def myFun(s: String, i: Int) = s + i
myFun: (s: String, i: Int)java.lang.String
scala> Array("nami", "zoro", "usopp")
res17: Array[java.lang.String] = Array(nami, zoro, usopp)
scala> res17.iterator.zipWithIndex
res19: java.lang.Object with Iterator[(java.lang.String, Int)]{def idx: Int; def idx_=(x$1: Int): Unit} = non-empty iterator
scala> res19 map { case (k, v) => myFun(k, v) }
res22: Iterator[java.lang.String] = non-empty iterator
scala> res22.toArray
res23: Array[java.lang.String] = Array(nami0, zoro1, usopp2)
Keep in mind that iterators are mutable, and hence once consumed cannot be used again.
An aside: The map call above involves de-tupling and then function application. This forces use of some local variables. You can avoid that using some higher order sorcery - convert a regular function to the one accepting tuple, and then pass it to map.
scala> Array("nami", "zoro", "usopp").zipWithIndex.map(Function.tupled(myFun))
res24: Array[java.lang.String] = Array(nami0, zoro1, usopp2)
What about this? I think it should be fast and it's pretty. But I'm no expert on Scala speed...
a.foldLeft(0) ((i, x) => {myFn(x, i); i + 1;} )
Index can also be accessed via the second element of tuples generated by the zipWithIndex method:
val a = Array("One", "Two", "Three")
val b = a.zipWithIndex.map(s => myFn(s._1, s._2))

2d scala array iteration

I have a 2d array of type boolean (not important)
It is easy to iterate over the array in non-functional style.
How to do it FP style?
var matrix = Array.ofDim[Boolean](5, 5)
for ex, I would like to iterate through all the rows for a given column and return a list of int that would match a specific function.
Example: for column 3, iterate through rows 1 to 5 to return 4, 5 if the cell at (4, 3), (5, 3) match a specif function. Thx v much
def getChildren(nodeId: Int) : List[Int] = {
info("getChildren("+nodeId+")")
var list = List[Int]()
val nodeIndex = id2indexMap(nodeId)
for (rowIndex <- 0 until matrix.size) {
val elem = matrix(rowIndex)(nodeIndex)
if (elem) {
println("Row Index = " + rowIndex)
list = rowIndex :: list
}
}
list
}
What about
(1 to 5) filter {i => predicate(matrix(i)(3))}
where predicate is your function?
Note that initialized with (5,5) indexes goes from 0 to 4.
Update: based on your example
def getChildren(nodeId: Int) : List[Int] = {
info("getChildren("+nodeId+")")
val nodeIndex = id2indexMap(nodeId)
val result = (0 until matrix.size).filter(matrix(_)(nodeIndex)).toList
result.forEach(println)
result
}
You may move the print in the fiter if you want too, and reverse the list if you want it exactly as in your example
If you're not comfortable with filters and zips, you can stick with the for-comprehension but use it in a more functional way:
for {
rowIndex <- matrix.indices
if matrix(rowIndex)(nodeIndex)
} yield {
println("Row Index = " + rowIndex)
rowIndex
}
yield builds a new collection from the results of the for-comprehension, so this expression evaluates to the collection you want to return. seq.indices is a method equivalent to 0 until seq.size. The curly braces allow you to span multiple lines without semicolons, but you can make it in-line if you want:
for (rowIndex <- matrix.indices; if matrix(rowIndex)(nodeIndex)) yield rowIndex
Should probably also mention that normally if you're iterating through an Array you won't need to refer to the indices at all. You'd do something like
for {
row <- matrix
elem <- row
} yield f(elem)
but your use-case is a bit unusual in that it requires the indices of the elements, which you shouldn't normally be concerned with (using array indices is essentially a quick and dirty hack to pair a data element with a number). If you want to capture and use the notion of position you might be better off using a Map[Int, Boolean] or a case class with such a field.
def findIndices[A](aa: Array[Array[A]], pred: A => Boolean): Array[Array[Int]] =
aa.map(row =>
row.zipWithIndex.collect{
case (v,i) if pred(v) => i
}
)
You can refactor it to be a bit more nicer by extracting the function that finds the indices in a single row only:
def findIndices2[A](xs: Array[A], pred: A => Boolean): Array[Int] =
xs.zipWithIndex.collect{
case (v,i) if pred(v) => i
}
And then write
matrix.map(row => findIndices2(row, pred))

Resources