So, I wrote a code to compare sorting algorithms. I implemented a few algs as separate classes. Here is a couple for explanation sake.
class BubbleSort(input:ListBuffer[Int]){
...
}
class InsertionSort(input:ListBuffer[Int]){
...
}
From my driver object, I first create a list, called input.
Next, I pass this to new instances of BubbleSort and InsertionSort.
Then I call a function sort, which sorts the ListBuffer I passed during object creation.
val input = new ListBuffer[Int]
//Populated input here
val bs = new BubbleSort(input)
val is = new InsertionSort(input)
bs.sort
is.sort
The issue I'm facing is, when is.sort is called, the list I passed during object creation is already sorted. I guess this is because I called bs.sort first, but why does it affect a list in another class?
Any help is appreciated. If you want more code snippets, I'll be glad to share. Thanks in advance!
EDIT
As a temporary fix, instead of creating only one list input, I resorted to boilerplate code and created two lists,bsinput and isinput. Each is then passed to separate classes.
val bsinput = new ListBuffer[Int]
val isinput = new ListBuffer[Int]
//Populated both arrays with the same data
val bs = new BubbleSort(bsinput)
val is = new InsertionSort(isinput)
bs.sort
is.sort
This solves the problem, but is this the only way? Is there an idiomatic way of doing this?
Edit 2
As #LuisMiguelMejíaSuárez said it was a reference issue. Used input.clone and it works now.
You're passing twice a reference to the same mutable collection ListBuffer.
It means both of your sorting algorithms will be working on the same collection and therefore on the second time, your list buffer will be already sorted.
To avoid accidental mutations you just need to create a defensive copy each time you pass it:
val input1 = new ListBuffer[Int]
//Populated input here
val input2 = input1.clone
val bs = new BubbleSort(input1)
val is = new InsertionSort(input2)
Related
Given an array of items I need to generate a sorted collection in Scala for a java.lang.reflect.Type but I'm unable to do so. The following snippet might explain better.
def buildList(paramType: Type): SortedSet[_] = {
val collection = new Array[Any](5)
for (i <- 0 until 5) {
collection(i) = new EasyRandom().nextObject(paramType.asInstanceOf[Class[Any]])
}
SortedSet(collection:_*)
}
I'm unable to do as I get the error "No implicits found for parameter ord: Ordering[Any]". I'm able to work around this if I swap to an unsorted type such as Set.
def buildList(paramType: Type): Set[_] = {
val collection = new Array[Any](5)
for (i <- 0 until 5) {
collection(i) = new EasyRandom().nextObject(paramType.asInstanceOf[Class[Any]])
}
Set(collection:_*)
}
How can I dynamically build a sorted set at runtime? I've been looking into how Jackson tries to achieve the same but I couldn't quite follow how to get T here: https://github.com/FasterXML/jackson-module-scala/blob/0e926622ea4e8cef16dd757fa85400a0b9dcd1d3/src/main/scala/com/fasterxml/jackson/module/scala/introspect/OrderingLocator.scala#L21
(Please excuse me if my question is unclear.)
This happens because SortedSet needs a contextual (implicit) Ordering type class instance for a given type A
However, as Luis said on the comment section, I'd strongly advice you against using this approach and using a safer, strongly typed one, instead.
Generating random case classes (which I suppose you're using since you're using Scala) should be easy with the help of some libraries like magnolia. That would turn your code into something like this:
def randomList[A : Ordering : Arbitrary]: SortedSet[A] = {
val arb: Arbitrary[A] = implicitly[Arbitrary[A]]
val sampleData = (1 to 5).map(arb.arbitrary.sample)
SortedSet(sampleData)
}
This approach involves some heavy concepts like implicits and type classes, but is way safer.
I am wondering what is the best way to save the initial state of an Array in scala so I can reset with initial values after manipulating a working copy. I would like to do something like this
val initialValue = Array(Array(1,2,3),Array(4,5,6))
val workingCopy = initialValue.clone
The problem is that when I change values of workingCopy, I also change the values of initialValue.
I also tried
val workingCopy = Array.fill(2,3)(0)
Array.copy(initialValue,0,workingCopy,2)
But I get the same result.
This holds even if i use var instead of val when defining the arrays. I think this shallow copy behavior might be caused by the nested Array structure, but I'm not sure how to deal with it.
As pointed out by Angelo, you usually want to use immutable data structures to avoid problems like this. However, if you really need to go the mutable way, e.g. for performance reasons (although the "modification" of immutable collections, such as Vector, is not as expensive as you might think), then you need to do a deep copy of your nested arrays and the content. The implementation is up to you.
If it really is just an Array[Array[Int]], it's enough to do something like this:
val initialValue = Array(Array(1,2,3), Array(4,5,6))
val workingCopy = initialValue.map(_.clone)
A more general example using a reference type instead of simple Ints:
scala> class Cell(var x: String) { def copy = new Cell(x); override def toString = x }
defined class Cell
scala> val initialValue = Array(Array(new Cell("foo")))
initialValue: Array[Array[Cell]] = Array(Array(foo))
scala> val workingCopy = initialValue.map(_.map(_.copy))
workingCopy: Array[Array[Cell]] = Array(Array(foo))
scala> initialValue(0)(0).x = "bar"
initialValue(0)(0).x: String = bar
scala> initialValue
res0: Array[Array[Cell]] = Array(Array(bar))
scala> workingCopy
res1: Array[Array[Cell]] = Array(Array(foo))
Instead of initialValue.map(_.map(_.copy)), there are of course other ways to do the same thing (e.g. a nested for expression which copies the objects as its side effect).
var vs val really just determines whether the reference is immutable, it would have no effect on the contents of the data structure. if you were to convert to an immutable data structure, for example a List, then the copy would be unneeded as the operations for "modifying" the contents of such a structure create a new reference leaving the original untouched.
for example:
val initialValue = List(List(1,2,3),List(4,5,6))
val sumInnerLists = initialValue.map(l => l.foldLeft(0)(_ + _))
println(sumInnerLists) // List(6, 15)
println(initialValue) // List(List(1,2,3),List(4,5,6))
Background
I have a java.util.List[Array[String]] called rawdata coming directly from opencsv's CSVReader
val reader = new CSVReader( new FileReader( "foobar.csv" ))
val rawdata = reader.readAll();
Currently, I'm looping through rawdata and grabbing rawdata.get(i)(4) and rawdata.get(i)(5) for fields 4 and 5 in record i where i goes from 0 to 99,999.
Problem
Instead, I would like to map rawdata into a Vector[Record] where the constructor for Record takes fields 4 and 5 from above. There are 100,000 records in rawdata.
This is where I hit a bit of cognitive dissonance because Vector is immutable, but java.util.List[Array[String]] requires that I loop through it (there is no map for me to call, AFAIK)...
Question
How do I map the java.util.List[Array[String]] to Vector[Record]?
Scala provides a set of conversions from Java collections, which you can use like this:
import scala.collection.JavaConverters._
val records = rawdata.asScala.toVector.map(toRecord)
Where toRecord is some method like the following:
def toMethod(fields: Array[String]) = Record(fields(4), fields(5))
You could also perform the mapping operation with a function literal:
val records = rawdata.asScala.toVector.map { fields =>
Record(fields(4), fields(5))
}
Both of these versions will convert the java.util.List to a scala.collection.mutable.Buffer, then to a Vector, and then perform the mapping operation. You could save one intermediate collection like this:
val records: Vector[Record] = rawdata.asScala.map(toRecord)(collection.breakOut)
Or you could convert to an iterator on the Java side:
val records = rawdata.iterator.asScala.map(toRecord).toVector
The simplest version's probably best, though, unless you're sure this is a bottleneck in your program.
I wanted to ensure I understand some scala code correctly. I have a method in a class as:
def getNodes(): IndexedSeq[Node] = allNodes
Then somewhere this method gets called as:
val nodes = graph.getNodes()
and then there is a line
val orderedNodes = nodes ++ nodes.reverse
Does this make another sequence where the original sequence and the reversed get concatenated or is there some other subtlety to it as well?
Yes, the result is a new IndexedSeq containing items just like you wrote. You're calling methods ++ and reverse that are well documented here:
http://www.scala-lang.org/api/2.10.3/index.html#scala.collection.IndexedSeq
Your code can be written like this:
val orderedNodes = nodes.++(nodes.reverse)
I am trying to add and object to a list not just a number so when you reply with an example if you could use an object like my used car example or a fruit or something
I've been looking every where and all the examples i see are just adding numbers to a list.
Im trying to convert some java code into scala
the java code im having trouble converting is
ArrayList usedCarList = new ArrayList();
UsedCars usedCar = new UsedCars();
usedCarList.add(usedCar);
Now i've looked at a few examples but they dont seem to work once i start trying to use an object ie
var b = List[Int]();
b ::= 1;
b ::= 2;
b ::= 3;
I've tried a few things 1 is listed below.
var usedCarList = List();
def addCar (usedCarList: List[UsedCars]){
var usedCar = new UsedCars();
series of set operations on the usedCar
usedCar :: usedCarList;
println(usedCarList.length);
}
when i check the size of the list its always empty
There are mutable (such as scala.collection.mutable.MutableList) and immutable lists (scala.collection.immutable.List). What you're using are immutable lists, so by just calling :: on an element actually returns a new instance with the added element, but doesn't change the underlying value. You'd have to either use a var with an immutable list, or use a mutable one like this:
scala> import scala.collection._
import scala.collection._
scala> val list = mutable.MutableList[UsedCars]()
list: scala.collection.mutable.MutableList[UsedCars] = MutableList()
scala> list += new UsedCars()
res0: list.type = MutableList(UsedCars#4bfa79c8)
scala> list.size
res1: Int = 1
See su-'s answer for reassigning the reference with the immutable lists.
There's a fundamental distinction between Scala's List and Java's ArrayList: Scala's List is immutable.
Not simply read only -- a read only collection in Java may still be changed by whoever created it. In Scala, a List cannot be changed by anyone.
Now, let's reconcile that with the example you showed that "works": b ::= 1. That example is equivalent to b = 1 :: b, so it isn't changing the list. Instead, it is creating a new list, and assigning it to b. That may sound inefficient, but it is actually quite fast because List is a persistent data structure (look that up for more information).
The most obvious answer to your question, therefore, is to use a different kind of data structure. Scala's closest equivalent to ArrayList is the ArrayBuffer.
However, there's another possibility that may be pursued. Instead of changing the list and returning nothing, return a new list. That may well require other changes to the structure of the code, and since there's no detail about it, I won't speculate on what they might be.