I am new to Scala and this is the first time I'm using it. I want to read in a textfile with with two columns of numbers and store each column items in a separate list or array that will have to be cast as integer. For example the textfile looks like this:
1 2
2 3
3 4
4 5
1 6
6 7
7 8
8 9
6 10
I want to separate the two columns so that each column is stored in its on list or array.
Lets say you named the file as "columns", this would be a solution:
val lines = Source.fromFile("columns").getLines()
/* gets an Iterator[String] which interfaces a collection of all the lines in the file*/
val linesAsArraysOfInts = lines.map(line => line.split(" ").map(_.toInt))
/* Here you transform (map) any line to arrays of Int, so you will get as a result an Interator[Array[Int]] */
val pair: (List[Int], List[Int]) = linesAsArraysOfInts.foldLeft((List[Int](), List[Int]()))((acc, cur) => (cur(0) :: acc._1, cur(1) :: acc._2))
/* The foldLeft method on iterators, allows you to propagate an operation from left to right on the Iterator starting from an initial value and changing this value over the propagation process. In this case you start with two empty Lists stored as Tuple an on each step you prepend the first element of the array to the first List, and the second element to the second List. At the end you will have to Lists with the columns in reverse order*/
val leftList: List[Int] = pair._1.reverse
val rightList: List[Int] = pair._2.reverse
//finally you apply reverse to the lists and it's done :)
Here is one possible way of doing this:
val file: String = ??? // path to .txt in String format
val source = Source.fromFile(file)
scala> val columnsTogether = source.getLines.map { line =>
val nums = line.split(" ") // creating an array of just the 'numbers'
(nums.head, nums.last) // assumes every line has TWO numbers only
}.toList
columnsTogether: List[(String, String)] = List((1,2), (2,3), (3,4), (4,5), (1,6), (6,7), (7,8), (8,9), (6,10))
scala> columnsTogether.map(_._1.toInt)
res0: List[Int] = List(1, 2, 3, 4, 1, 6, 7, 8, 6)
scala> columnsTogether.map(_._2.toInt)
res1: List[Int] = List(2, 3, 4, 5, 6, 7, 8, 9, 10)
Related
Assume that I have an array like 1 2 3 4 5, I want to rotate it to the left by n and get a new one.
For example the 2 rotation of the above array will result in 3 4 5 1 2. I didn't found any extension function to do that.
You can use built-in java Collections.rotate method, but you need to convert your array to list firstly:
val arr = intArrayOf(1, 2, 3, 4, 5)
val list = arr.toList()
Collections.rotate(list, -2)
println(list.toIntArray().joinToString())
Outputs
3, 4, 5, 1, 2
I interpret "get a new one" to mean that the extension function should return a new array instance, like so (boundary checks omitted, sliceArray is an stdlib function) :
fun <T> Array<T>.rotate(n: Int) =
let { sliceArray(n until size) + sliceArray(0 until n) }
Example
arrayOf(1, 2, 3, 4, 5).rotate(1)
.also { println(it.joinToString()) } // 2, 3, 4, 5, 1
Another extension function, by slicing the array in 2 parts left and right and reassembling it to right + left:
fun <T> Array<T>.leftShift(d: Int) {
val n = d % this.size // just in case
if (n == 0) return // no need to shift
val left = this.copyOfRange(0, n)
val right = this.copyOfRange(n, this.size)
System.arraycopy(right, 0, this, 0, right.size)
System.arraycopy(left, 0, this, right.size, left.size)
}
so this:
val a = arrayOf(1, 2, 3, 4, 5, 6, 7)
a.leftShift(2)
a.forEach { print(" " + it) }
will print
3 4 5 6 7 1 2
Simple solution:
fun <T> Array<T>.rotateLeft(n: Int) = drop(n) + take(n)
fun <T> Array<T>.rotateRight(n: Int) = takeLast(n) + dropLast(n)
The limitation is that n must be less than or equal to the length of the array.
Alternatively, you can use Collections.rotate(...) as follows.
import java.util.Collections
fun <T> Array<T>.rotate(distance: Int) =
toList().also { // toList() is a deep copy to avoid changing the original array.
Collections.rotate(it, distance)
}
fun main() {
val xs = arrayOf(1, 2, 3, 4, 5)
val ys = xs.rotate(-2)
xs.forEach { print("$it ") } // 1 2 3 4 5
println(ys) // [3, 4, 5, 1, 2]
}
For the record, you can use the regular Array constructor to build a new array:
inline fun <reified T> Array<T>.rotate(n: Int) = Array(size) { this[(it + n) % size] }
The element at index it in the source array is copied in the destination array at the new index (it + n) % size to perform the rotation.
It is a bit slower than copying the array by chunks.
I've got an array that contains Integers as the one shown below:
val my_array = Array(10, 20, 6, 31, 0, 2, -2)
I need to get the maximum 3 elements of this array along with their corresponding indices (either using a single function or two separate funcs).
For example, the output might be something like:
// max values
Array(31, 20, 10)
// max indices
Array(3, 1, 0)
Although the operations look simple, I was not able to find any relevant functions around.
Here's a straightforward way - zipWithIndex followed by sorting:
val (values, indices) = my_array
.zipWithIndex // add indices
.sortBy(t => -t._1) // sort by values (descending)
.take(3) // take first 3
.unzip // "unzip" the array-of-tuples into tuple-of-arrays
Here's another way to do it:
(my_array zip Stream.from(0)).
sortWith(_._1 > _._1).
take(3)
res1: Array[(Int, Int)] = Array((31,3), (20,1), (10,0))
I want to find multiple elements of a value in an array in Matlab code.
I found the function mod and find, but these return the indices of elements and
not the elements. Moreover, I wrote the following code:
x=[1 2 3 4];
if (mod(x,2)==0)
a=x;
end
but this does not work. How can I solve this problem?
Looks like you what to find all multiples of 2 (or any number), you can achieve this using :
a = x( mod(x,2) == 0 ) ;
When you do a = x, x is still x=[1 2 3 4] regardless if (mod(x,2)==0) is true or false;
you can assign a value to (mod(x,2)==0), e.g. val = (mod(x,2)==0), then append/add this value to a new array.
Given a vector numberList = [ 1, 2, 3, 4, 5, 6]; and a number number = 2; you can find indices (position in a vector) of the numbers in the numberList that are a multiple of number using indices = find(mod(numberList, number) ==0);.
If necessary you may display a list of this multiples calling: multiples = numberList(indices).
multiples =
2 4 6
what's the efficient way to sum up every n elements of an array in Scala? For example, if my array is like below:
val arr = Array(3,1,9,2,5,8,...)
and I want to sum up every 3 elements of this array and get a new array like below:
newArr = Array(13, 15, ...)
How can I do this efficiently in Spark Scala? Thank you very much.
grouped followed by map should do the trick:
scala> val arr = Array(3,1,9,2,5,8)
arr: Array[Int] = Array(3, 1, 9, 2, 5, 8)
scala> arr.grouped(3).map(_.sum).toArray
res0: Array[Int] = Array(13, 15)
Calling the toIterator method on the array before calling grouped should speed things up a bit, i.e.
arr.toIterator.grouped(3).map(_.sum).toArray
For example, using
val xs = Array.range(0, 10000)
10000 iterations of
xs.toIterator.grouped(3).map(_.sum).toArray
takes about 16.93 seconds, while 10000 iterations of
xs.grouped(3).map(_.sum).toArray
requires approximately 21.49 seconds.
I have the following array, with (I think) sub lists within it:
items = [('this', 5, 'cm'), ('that', 3, 'mm'), ('other', 15, 'mm')]
I need to read it into new values for future calculations.
For example:
item1 = this
size1 = 5
unit1 = cm
item2 = that
size2 = 3
unit2 = mm
...
There may be more than 3 items in future arrays, so ideally some form of loop is needed?
Arrays in Python can be of 2 types - Lists & Tuples.
list is mutable (i.e. you can change the elements as & when you wish)
tuple is immutable (read only array)
list is represented by [1, 2, 3, 4]
tuple is represented by (1, 2, 3, 4)
Thus, the given array is a list of tuples!
You can nest tuples in lists but not lists in tuples.
This is more pythonic -
items = [('this', 5, 'cm'), ('that', 3, 'mm'), ('other', 15, 'mm')]
found_items = [list(item) for item in items]
for i in range(len(found_items)):
print (found_items[i])
new_value = int(input ("Enter new value: "))
for i in range(len(found_items)):
recalculated_item = new_value * found_items[i][1]
print (recalculated_item)
Output from above code (taking input as 3)
['this', 5, 'cm']
['that', 3, 'mm']
['other', 15, 'mm']
15
9
45
Update : Following up on this comment & this answer I've updated the above code.
Following on Ashish Nitin Patil's answer...
If there are are going to be more than three items in the future you can use the asterisk to unpack the items in the tuples.
items = [('this', 5, 'cm'), ('that', 3, 'mm'), ('other', 15, 'mm')]
for x in items:
print(*x)
#this 5 cm
#that 3 mm
#other 15 mm
Note: Python 2.7 doesn't seem to like the asterisk in the print method.
Update:
It looks like you need to use a second list of tuples that defines the property names of each value tuple:
props = [('item1', 'size2', 'unit1'), ('item2', 'size2', 'unit2'), ('item3', 'size3', 'unit3')]
values = [('this', 5, 'cm'), ('that', 3, 'mm'), ('other', 15, 'mm')]
for i in range(len(values)):
value = values[i]
prop = props[i]
for j in range(len(item)):
print(prop[j], '=', value[j])
# output
item1 = this
size2 = 5
unit1 = cm
item2 = that
size2 = 3
unit2 = mm
item3 = other
size3 = 15
unit3 = mm
The caveat here is that you need to make sure that the elements in the props list are matched sequentially with the elements in the values list.