I'm VERY new to Scala so apologies if anything sounds a bit basic. Working on a uni assignment and can't seem to find any similar questions around.
EDIT: The idea of this function is that I pass through a string of data and separate it up into individual elements. From what I can tell, things are being separated correctly with the lists holding the correct data types and correct information.
So I've created a function that returns a Map[String, List[(Int, String, Float)]]
The function does other things, but to keep it short, once I've build the list this is how I build the map and return it: -
val newMap = Map(name -> newList2.toList)
newMap
I can newMap.foreach to cycle through the map and find all of my elements. This works as expected: -
(Sample Key,List((3,PlaceName1,2.7)))
(Sample Key,List((2,PlaceName1,3.8)))
(Sample Key,List((1,PlaceName1,0.75)))
I am simply trying to call this function and save the map into a new variable. I have tried this two ways: -
val saveMap = separator("1:PlaceName1:0.75,2:PlaceName2:3.8,3:PlaceName3:2.7")
However when I try to cycle through this, I only get the first list element: -
(Sample Key,List((1,PlaceName1,0.75)))
I have also tried to use a mapBuffer in the format of: -
var mapBuffer: Map[String, List[(Int, String, Float)]] = Map()
mapBuffer = separator("1:PlaceName1:0.75,2:PlaceName2:3.8,3:PlaceName3:2.7")
Again, all I get as my return here is: -
mutated mapBuffer
(Sample Key,List((1,PlaceName1,0.75)))
Being new to Scala but with some experience in Java and C#, it's killing me how I'm returning a Map value, saving it into a map value that is built the same, and it's not coming through. Tried every iteration of maps and lists I could find and can't find anything on this from searching.
Is anyone able to offer any assistance?
EDIT:
Here is the whole code for the function and how I am attempting to call it.
def separator(data:String): Map[String, List[(Int, String, Float)]] = {
//Route name will be worked out later. For now, this is a sample.
val sampleRouteName = "First Route"
//Stage list will hold each list entry
val stageList = ListBuffer[(Int, String, Float)]()
//Stage list builder will put all the list entries together
var stageListBuilder = List[(Int, String, Float)]()
if (data.contains(",")) {
//Find index of first comma
val commaIndex = data.indexOf(",")
//Split everything before the comma off
val (firstEntry, restOfPhrase) = data.splitAt(commaIndex)
//Find the index of the colon in the first entry
val colonIndex = firstEntry.indexOf(":")
//Split everything before the colon off to just keep the number
val (number, restOfStage) = firstEntry.splitAt(colonIndex)
//Get rid of the first colon from the rest of the line
val restOfStage2 = restOfStage.replaceFirst(":", "")
//Find the index of the next colon
val colonIndex2 = restOfStage2.indexOf(":")
//Split everything before the colon off to just keep the stage name
val (stageName, restOfStage3) = restOfStage2.splitAt(colonIndex2)
//Get rid of the colon leaving just the stage length
val stageLength = restOfStage3.replaceFirst(":", "")
//Put all of these together into a list line in the builder
stageListBuilder = List((number.toInt,stageName,stageLength.toFloat))
//Add the list line from the builder to the list as an element
stageListBuilder.foreach(line => stageList += line)
//Call recursive function and remove the comma from the start
separator(restOfPhrase.replaceFirst(",", ""))
}
else if (data.length != 0) {
//Find index of first colon
val colonIndex = data.indexOf(":")
//Split everything before the colon off to just keep the number
val (number, restOfStage) = data.splitAt(colonIndex)
//Get rid of the first colon from the rest of the line
val restOfStage2 = restOfStage.replaceFirst(":", "")
//Find the index of the next colon
val colonIndex2 = restOfStage2.indexOf(":")
//Split everything before the colon off to just keep the stage name
val (stageName, restOfStage3) = restOfStage2.splitAt(colonIndex2)
//Get rid of the colon leaving just the stage length
val stageLength = restOfStage3.replaceFirst(":", "")
//Put all of these together into a list line in the builder
stageListBuilder = List((number.toInt,stageName,stageLength.toFloat))
//Add the list line from the builder to the list as an element
stageListBuilder.foreach(line => stageList += line)
}
//This is a map that accurately contains the key (ie. GCU Route) and a list of the routes.
val routeMap = Map(sampleRouteName -> stageList.toList)
//To test that the list has all the elements (CURRENTLY WORKING)
routeMap.foreach(line => println("TEST - " + line))
//Return the map
routeMap
}
//val saveMap = separator("1:City Chambers:0.75,2:Velodrome:3.8,3:People's Palace:2.7")
//Create new map buffer
var mapBuffer: Map[String, List[(Int, String, Float)]] = Map()
//Call separator function
mapBuffer = separator("1:City Chambers:0.75,2:Velodrome:3.8,3:People's Palace:2.7")
//Test that each element is in the list (CURRENTLY NOT WORKING)
mapBuffer.foreach(line => println(line))
As you mentioned you are using same keys as a key of a Map. Let's imagine we have separator method like this:
val str = "1:PlaceName1:0.75,2:PlaceName2:3.8,3:PlaceName3:2.7"
def separator(str: String): List[(String, (Int, String, Float))] =
str.split(",").map(_.split(":")).toList.map(_.toList).collect {
case ii :: s :: d :: Nil =>
"Sample Key" -> (ii.toInt, s, d.toFloat)
}
separator(str).foearch(println)
// result:
(Sample Key,(1,PlaceName1,0.75))
(Sample Key,(2,PlaceName2,3.8))
(Sample Key,(3,PlaceName3,2.7))
if we convert our result to a Map we lose some elements with same key in this case Sample Key:
def separator1(str: String): Map[String, List[(Int, String, Float)]] =
str.split(",").map(_.split(":")).toList.map(_.toList).collect {
case ii :: s :: d :: Nil =>
"Sample Key" -> List((ii.toInt, s, d.toFloat))
}.toMap
separator1(str).foreach(println)
// result:
// (Sample Key,List((3,PlaceName3,2.7)))
So we cannot have the same keys as KEY of a Map. The KEYs of a Map should be a unique.
case class Aname(a: Int, b: String, c: Float)
def separator2(str: String): Map[String, List[Aname]] =
str.split(",").map(_.split(":")).toList.map(_.toList).collect {
case ii :: s :: d :: Nil =>
Aname(ii.toInt, s, d.toFloat)
}.groupBy(_.b)
separator2(str).foreach(println)
// result:
// (PlaceName3,List(Aname(3,PlaceName3,2.7)))
// (PlaceName2,List(Aname(2,PlaceName2,3.8)))
// (PlaceName1,List(Aname(1,PlaceName1,0.75)))
You can play with it here
Suppose
Val L = List(“apple”, “d”, “ass1”, “110mac”)
How to remove any contents appear in the second and third element from the list?
Like anything inside The second and third elements will always be removed.
You can't modify the List but you can create a new one using parts of the old:
val list = List(“apple”, “d”, “ass1”, “110mac”)
val list2 = list.take(1) ++ list.drop(3)
Note that this is robust to the case where the list has fewer than 4 elements.
You can zip elements with index and then remove elements at the indexes you want, like below:
val fruitList = List("apple", "orange", "banana", "apricot", "blueberry", "cherry")
val removeSet = Set(2,3) // This set contains indexes of fruits which should be removed from fruitList
val resultList = fruitList.zipWithIndex //zip fruits with indexes to get List[(fruit, index)]
.filter(x => !(removeSet.contains(x._2))) // filter List[(fruit, index)] to remove fruits present at indexes contained in removeSet
.map(_._1) // map List[(fruit, index)] to List[fruit]
println(resultList) // prints List(apple, orange, blueberry, cherry)
In Java we can create a new list from another like this:
List<Integer> list1 = new ArrayList<>();
list1.add(1)
list1.add(-10)
list1.add(12)
list1.add(37)
List<Integer> list2 = new ArrayList<>(list1);
how can we achieve the same result as above in Kotlin using listOf() or mutableListOf()?
You can use .toList() and .toMutableList() extensions to copy a container (an array, a collection, a sequence) into a new list:
val list1 = listOf(1, -10, 12, 37)
val list2 = list1.toList()
val mutableList2 = list2.toMutableList()
I'm trying to write a function in ML to delete an entry from a list, given an index.
So, for example, if I have a list L = [1,2,3,4,5] and want to delete 3 from the list, I can call delete(2, L), which should delete the element at index 2, which is 3.
I have a function for deleting from a list, given a specific item in the list, but was wondering how I could get an index from a list.
Below is my code from deleting a specific element from a list
fun delete(element, list_head::list_tail) =
if element = list_head then list_tail
else list_head::delete(element, list_tail);
You can use the pattern matcher to define your two base cases and then implement your delete in terms of these cases.
fun delete (_, nil) = nil
| delete (0, _::xs) = xs
| delete (i, x::xs) = x::del(i-1,xs);
Supposing I have a type defined as follows:
type State = { intList : int list }
and a value as follows:
let a = { intList = [1; 2; 3; 4] }
Now supposing I want a new value b with a's values with 5 added to the end. I can't figure out how to do it using the with syntax. Also I can't figure out how to get a new state having one fewer element, for example.
The with syntax (copy-and-update expression) doesn't allow for creating a record based on a modified property of another record, only copying some properties (intact) and replacing others. You can use normal record constructors:
let a = { intList = [1; 2; 3; 4] }
let b = { intList = a.intList # [1; 2; 3; 4; 5] }
let c = { intList = List.tail a.intList }
As Daniel said, there is no specific syntax to read a property from the record you are copy-and-updating. But you still can access it using normal dot notation:
let a = { intList = [1; 2; 3; 4] }
let b = { a with intList = a.intList # [5] }
Of course, in this case the with is pretty useless since you're updating all the fields, so you might as well just use the new record syntax (as shown by Daniel). But if the record also has fields that you want to preserve from a to b, this is how I would do it.