Reputation: 497
I have a ListBuffer declared like this:
var distances_buffer: ListBuffer[List[Any]] = ListBuffer.empty[List[Any]]
and I am trying to fill it with data like this:
for(current <- 0 to training_list_length - 1){
//A and B are examples
distances_buffer(current) ++= List[Any](A,B)
}
However I get the following error:
java.lang.IndexOutOfBoundsException: 0
What am I missing?
EDIT! More Info:
I have a list (Named: training_list) of points and their class. (x, y, class) :
training_list : List[((Double, Double, String))]
I also have an extra point with a x and a y value given.
My goal is to calculate the euclidean distance of the extra point from each point inside the training list, and create a result which look like this:
//example
List((x: Double, y: Double, class: String), distance: String)
List((4.3,3.0,Iris-setosa), 1.2529964086141665), (4.4,3.0,Iris-setosa), 1.341640786499874)...
As you can see, in the list I want to include the coordinates of the point (from the training_list), the class of the point and also the distance.
for(current <- 0 to training_list_length - 1){
val dist = eDistance(test_x, test_y, training_x(current), training_y(current))
distances_buffer += ListBuffer[Any](training_result(current),dist)
}
After the creation of this list I want to sort it based on the distances. Also stuck here!
Upvotes: 1
Views: 419
Reputation: 48400
As suggested by Luis, Any
and var
are to be avoided if possible, so here is an example that might nudge you to consider a different approach
case class Point(x: Double, y: Double, `class`: String)
def distance(a: Point, b: Point): Double =
math.hypot(a.x - b.x, a.y - b.y)
val targetPoint = Point(1,2,"Extra-point")
val training_list : List[((Double, Double, String))] = List((4.3,3.0,"Iris-setosa"), (4.4,3.0,"Iris-setosa"))
val points = training_list.map(Point.tupled)
val unsortedPoints: List[(Point, Double)] = points.map(point => (point, distance(point, targetPoint)))
unsortedPoints.sortBy(_._2)
which outputs
res0: List[(Point, Double)] = List((Point(4.3,3.0,Iris-setosa),3.4481879299133333), (Point(4.4,3.0,Iris-setosa),3.5440090293338704))
I have copied distance calculation from Xavier.
Upvotes: 2
Reputation: 22840
It seems, for the way you name things, that you come from a Python background.
I would advice you to study a little bit about Scala first, since we are very different.
Not only on style things (like camel case vs dash case), but on more fundamental things like:
Any
are usually a code smell and for 99.99% of cases, completely unnecessary.map
, flatMap
, filter
& reduce
.O(n)
(in Python it would be O(1)
). A Python list is more like an Array that can be resized.for
loop. We have something called for comprehension which is nothing more than syntactic sugar for calls to map
, flatMap
, filter
& in some cases foreach
.The list could go on, but I think my point is clear.
Scala is not only new syntax, is a different way to program.
Anyways, here is an idiomatic way to solve your problem.
(Not necessary this is the best way, there are many variations that can be done)
// First lets create some custom types / classes to represent your data.
final case class Point(x: Double, y: Double)
final case class ClassifiedPoint(point: Point, clazz: String)
// Lets define the Euclidean distance function.
def euclideanDistance(p1: Point, p2: Point): Double =
math.sqrt(
math.pow((p1.x - p2.x), 2) +
math.pow((p1.y - p2.y), 2)
)
}
// This is what you need.
// Note that I made it somewhat more generic that is has to be.
// For example, instead of using the euclidean distance function directly on the body,
// we receive the distance function to use.
// Also, I use a technique called currying to split the arguments in different lists,
// This allows the caller to partially apply them.
def computeDistance(distanceFun: (Point, Point) => Double)
(trainingList: List[ClassifiedPoint])
(referencePoint: Point): List[(ClassifiedPoint, Double)] =
trainingList.map { classifiedPoint =>
val distance = distanceFun(classifiedPoint.point, referencePoint)
classifiedPoint -> distance
}
Which you can use like this.
val trainingList = List(
ClassifiedPoint(Point(x = 4.3d, y = 3.0d), clazz = "Iris-setosa"),
ClassifiedPoint(Point(x = 4.4d, y = 3.0d), clazz = "Iris-setosa")
)
// Partial application to create a new function.
val computeEuclideanDistance = computeDistance(euclideanDistance) _
computeEuclideanDistance(trainingList, Point(x = 3.0d, y = 0.0d))
// res: List[(ClassifiedPoint, Double)] =
// List(
// (ClassifiedPoint(Point(4.3, 3.0), "Iris-setosa"), 3.269556544854363),
// (ClassifiedPoint(Point(4.4, 3.0), "Iris-setosa"), 3.3105890714493698)
// )
Upvotes: 3