Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
I have tried:
for(i<-0 to arr.length){
println(i)
if(a(i) > a(i+1)){
var tempVal: Int = a(i)
a(i)= a(i+1)
a(i+1) = tempVal
}
}
The example I tried is: [1,2,8,5,10]. I want to sort this array without using any type of the built-in sorted scala functions. When I try the above, it throws: Index 4 out of bounds for length 4. How can I fix this? Is there any better way to sort an array in Scala?
You can find in the Scala By Example book, in chapter 2, an example for a sort, without using a .sort kind of function:
def sort(xs: Array[Int]): Array[Int] = {
if (xs.length <= 1) xs
else {
val pivot = xs(xs.length / 2)
Array.concat(
sort(xs filter (pivot >)),
xs filter (pivot ==),
sort(xs filter (pivot <)))
}
}
If you want to read more about this algorithm, you can do it at Scala Quicksort algorithms: FP/recursive, imperative (and performance). This article also analyses the memory complexity.
Welcome to Scala. In Software Engineering there are multiple ways to sort outside of the standard library. One way to understand the different ones is to watch some of the Hungarian dancers entertain you with:
Quicksort https://www.youtube.com/watch?v=ywWBy6J5gz8
Bubblesort https://www.youtube.com/watch?v=lyZQPjUT5B4
But in answer to your question. It is kind of tough since a doesn't necessarily refer to anything and we don't know what arr originally looks like.
I redid a bit, the other thing is, this looks like a bubble sort, so you would have to ensure that you do a pass with no swaps. Here you will get a response at least, but it is still incorrect, post an update, and read about bubble sort. By the way, your check at the last element was reaching out of bounds .:)
val arr = Array(10, 3, 4, 9, 2, 5, 1)
for(i<-0 to (arr.length -1 )){
if(i < (arr.length -1) && arr(i) > arr(i+1)){
var tempVal: Int = arr(i)
arr(i)= arr(i+1)
arr(i+1) = tempVal
}
}
println(arr.mkString(","))
Let's go through your code one step at a time. First of all, as an example I'll say that
val a = Array(5, 3, 4, 7, 1)
I'll let the formatter tidy up my code, fix the reference to arr (it should be a, judging from the rest of the code) and get rid of the debug print.
We get to this point (playground):
val a = Array(5, 3, 4, 7, 1)
for (i <- 0 to a.length) {
if (a(i) > a(i + 1)) {
var tempVal: Int = a(i)
a(i) = a(i + 1)
a(i + 1) = tempVal
}
}
Now at least the code compiles. As suggested in a comment, one error is using to to produce a range: as you are correctly assuming that array indexes are 0 based. However, this means that an array of length 5 (as in my case) will have valid indexes in the range 0 to 4. The to method produces a range which includes the specified ends, so 0 to a.length will create the range 0 to 5, where 5 will cause the IndexOutOfRangeException. Again, as suggested in the comment, we should replace to with until, which yields the same result as 0 to (n - 1).
Furthermore, you are indexing the next element inside the loop, which means that you want to loop the array until the second to last element, which means we need to iterate from 0 until (a.length - 1).
After this change the code also runs, so I'll add a println at the end to see the result (playground):
for (i <- 0 until (a.length - 1)) {
if (a(i) > a(i + 1)) {
var tempVal: Int = a(i)
a(i) = a(i + 1)
a(i + 1) = tempVal
}
}
println(a.iterator.mkString(", "))
Unfortunately this prints 3, 4, 5, 1, 7, which is definitely not sorted.
It looks like you are implementing bubble sort, but in order to do that we cannot simply go through the array once, we need to iterate over and over again until the array is sorted. We'll introduce a boolean variable to keep track of whether we reached the desired conclusion (playground):
val a = Array(5, 3, 4, 7, 1)
var needsSorting = true
while (needsSorting) {
needsSorting = false
for (i <- 0 until (a.length - 1)) {
if (a(i) > a(i + 1)) {
var tempVal: Int = a(i)
a(i) = a(i + 1)
a(i + 1) = tempVal
needsSorting = true
}
}
}
println(a.iterator.mkString(", "))
Now the output is 1, 3, 4, 5, 7, which is sorted! This successfully implements a bubble sort, which is however a very inefficient algorithm, requiring to go through the entire array once for every item in the array, which means that it has quadratic complexity.
The next step for you is learning more on more efficient sorting algorithms.
In the meantime, we can probably have a look at the code and improve where possible. A first step could be to remove the unnecessary mutable variable when swapping and factor out the swap method (playground):
def swap(a: Array[Int], i: Int, j: Int): Unit = {
val tmp = a(j)
a(j) = a(i)
a(i) = tmp
}
val a = Array(5, 3, 4, 7, 1)
var needsSorting = true
while (needsSorting) {
needsSorting = false
for (i <- 0 until (a.length - 1)) {
if (a(i) > a(i + 1)) {
swap(a, i, i + 1)
needsSorting = true
}
}
}
println(a.iterator.mkString(", "))
Another thing I would do is factor out sorting in its own function (playground):
def swap(a: Array[Int], i: Int, j: Int): Unit = {
val tmp = a(j)
a(j) = a(i)
a(i) = tmp
}
def sort(a: Array[Int]): Unit = {
var needsSorting = true
while (needsSorting) {
needsSorting = false
for (i <- 0 until (a.length - 1)) {
if (a(i) > a(i + 1)) {
swap(a, i, i + 1)
needsSorting = true
}
}
}
}
val a = Array(5, 3, 4, 7, 1)
sort(a)
println(a.iterator.mkString(", "))
Another thing I would do is probably to factor out a single pass as its own method and declare both helpers in the sort function itself to limit the scope in which they can be used and take advantage of a being in scope so that we don't have to pass it in (playground):
def sort(a: Array[Int]): Unit = {
val secondToLastItem = a.length - 1
def swap(i: Int, j: Int): Unit = {
val tmp = a(j)
a(j) = a(i)
a(i) = tmp
}
def onePassIsSorted(): Boolean = {
var swapped = false
for (i <- 0 until secondToLastItem) {
val j = i + 1
if (a(i) > a(j)) {
swap(i, j)
swapped = true
}
}
swapped
}
while (onePassIsSorted()) {}
}
val a = Array(5, 3, 4, 7, 1)
sort(a)
println(a.iterator.mkString(", "))
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.
Hi I've tried to insert element to rdd array[String] using scala in spark.
Here is example.
val data = RDD[Array[String]] = Array(Array(1,2,3), Array(1,2,3,4), Array(1,2)).
I want to make length 4 of all arrays in this data.
If the length of array is less than 4, I want to fill the NULL value in the array.
here is my code that I tried to solve.
val newData = data.map(x =>
if(x.length < 4){
for(i <- x.length until 4){
x.union("NULL")
}
}
else{
x
}
)
But The result is Array[Any] = Array((), Array(1, 2, 3, 4), ()).
So I tried another ways. I used yield on for loop.
val newData = data.map(x =>
if(x.length < 4){
for(i <- x.length until 4)yield{
x.union("NULL")
}
}
else{
x
}
)
The result is Array[Object] = Array(Vector(Array(1, 2, 3, N, U, L, L)), Array(1, 2, 3, 4), Vector(Array(1, 2, N, U, L, L), Array(1, 2, N, U, L, L)))
these are not what I want. I want to return like this
RDD[Array[String]] = Array(Array(1,2,3,NULL), Array(1,2,3,4), Array(1,2,NULL,NULL)).
What should I do?
Is there a method to solve it?
union is a functional operation, it doesn't change the array x. You don't need to do this with a loop, though, and any loop implementations will probably be slower -- it's much better to create one new collection with all the NULL values instead of mutating something every time you add a null. Here's a lambda function that should work for you:
def fillNull(x: Array[Int], desiredLength: Int): Array[String] = {
x.map(_.toString) ++ Array.fill(desiredLength - x.length)("NULL")
}
val newData = data.map(fillNull(_, 4))
I solved your use case with the following code:
val initialRDD = sparkContext.parallelize(Array(Array[AnyVal](1, 2, 3), Array[AnyVal](1, 2, 3, 4), Array[AnyVal](1, 2, 3)))
val transformedRDD = initialRDD.map(array =>
if (array.length < 4) {
val transformedArray = Array.fill[AnyVal](4)("NULL")
Array.copy(array, 0, transformedArray, 0, array.length)
transformedArray
} else {
array
}
)
val result = transformedRDD.collect()
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 do I put values from a sorted list and array into a dictionary and determine how many time numbers repeat themselves? This is my code so far.
from numpy import *
from random import *
lista=[]
for x in range(0,20):
broj=input("Unesi %d broj>>" % (x+1))
lista.append(broj)
print"Nesortirana lista>>",lista
while True:
ne=False
for b in range(0,len(lista)-1):
if lista[b] > lista[b+1]:
pomocna=lista[b]
lista[b]=lista[b+1]
lista[b+1]=pomocna
ne=True
if ne == False:
break
print "Sortirana lista",lista
velicina_polja = 10
polje = array(velicina_polja * [0])
for i in range(0, velicina_polja):
polje[i] = randrange(1, 11)
print "Nesortirano polje:", polje
ima_promjene = True
while ima_promjene:
ima_promjene = False
for i in range(0, velicina_polja - 1):
if polje[i] > polje[i + 1]:
polje[i], polje[i + 1] = polje[i + 1], polje[i]
ima_promjene = True
print "Sortirano polje:", polje
I think you want something like this:
#!/usr/bin/env python
if __name__ == "__main__":
my_list = [ 1, 2, 3, 3]
my_dict = {}
for item in my_list:
my_dict[item] = my_dict.get(item, 0) + 1
for key in my_dict.keys():
print key, ":", my_dict[key]
It adds one to the count for a given key. If the key is not already in the dictionary, it assumes a value of zero and then increments that.
So the above example prints:
1 : 1
2 : 1
3 : 2