I'm looking for a function:
def fun(init:Int,level:Int)
Such that:
fun(1,1) == List(1)
fun(1,2) == List(List(1),List(1))
This task is very easy in java by using a for iteration. How can I write it in Scala using the functional programing style?
You can use List.fill for this. The first parameter list of this method has many overloads of variable length, and represents the number of elements at each level of nesting. The second argument is the element to fill:
List.fill(1, 1)(1) //List(List(1))
List.fill(1, 2, 3)(4) //List(List(List(4, 4, 4), List(4, 4, 4)))
The full method definition you're looking for doesn't fit very well in to Scala, because the return type would be the least common super type of List[Int], List[List[Int]], List[List[List[Int]]], etc.), which would be Any or List[Any] depending on your definition of fun(1, 0). It would look something like this:
def fun(init: Int, level: Int): Any = level match {
case 0 => init
case n => List(fun(init, level - 1))
}
But this really isn't recommended and would be considered unidiomatic in most Scala environments.
You can solve it with the help of a recursive function:
def fun(init:Int, level:Int):List[_] = {
if(level <= 1)
List(init)
else
List.make(level, fun(init, level-1))
}
At every level it creates a list with the same number of elements as the level is by using the make function of the List object. The Elements you are creating are also Lists whith one element less then the current level is. The end condition of your function is when the number is smaller or equal to 1. That's the moment you simply return a list with the init value as Element.
A type-safe approach involves the use of a tree for instance defined as follows,
trait Tree
case class Branch(t: List[Tree]) extends Tree
case class Leaf(i: Int) extends Tree
Then for example
val tree1 = Branch(List( Branch(List(Leaf(1),Leaf(2))), Leaf(3)))
where each consecutive Branch(List()) pattern corresponds to 1 level.
Related
I have below HOF which takes function as an argument
def findFirst[A](ss:Array[A], p:A=>Boolean):Int ={
#tailrec
def loop(n:Int):Int ={
if(p(ss(n))) n
else if (n+1>=ss.length) -1
else loop(n+1)
}
loop(0)
}
I can call the above function with the below parameters but I am wondering is there any better way to implement p?
println(findFirst(Array(6, 1,2,3,4,5,6) ,(a:Int)=> a.equals(6)))
So only regarding the "nicer way to implement the p", and assuming your coding in Scala 2 (based on the coding style), I suggest you do this:
def findFirst[A](ss: Array[A])(p: A => Boolean): Int = ...
// And then when calling the function:
findFirst(Array(1, 2, 3, 4, 5, 6))(_ == 6)
That's because in Scala 2 type inference is done from the left-most parenthesis, so the A is inferred to be Int from the first arguments set, and you can pass the p function in a very concise manner. And also it makes more sense when you can use curried functions, doesn't it? You pass the array in the first argument set, and the function in the second one, it's like "find first elemnt in the array, that satisfies the p predicate"
With a background from object-oriented programming I am not able to understand how to make immutable lists in Scala.
Example; I want to make a list of 10 random people:
object MyApplication extends App {
val numberOfPersons = 10 : Int
val listOfPersons = makeListOfPersons(numberOfPersons) : List[Person]
def makeListOfPersons( numberOfPersons : Int ) : List[Person] = {
// TODO: return a immutable list of 10 persons
}
}
class Person {
/**
Generic content,
like age and name.
* */
}
What is the "correct" way of making an immutable list in Scala?
If you know what collection type you want, you may be able to use the tabulate method on that type:
List.tabulate(10)(makePerson)
In this case makePerson is a function that takes an Int and returns the Person object for that Int.
If you don't care about the collection type, you can call map on the range 1 to 10 like this:
(1 to 10).map(makePerson)
If you don't need to use the Int parameter, you can do this:
List.tabulate(10)(_ => makeRandomPerson())
In this particular case,
List.fill(numberOfPersons){ codeThatCreatesASinglePerson }
seems most appropriate.
In most other cases: Nil creates an empty list, x :: y prepends an element x to list y.
If you want to append to list, instead of prepending to it, then you can take a collection.mutable.ListBuffer, append to it all the elements that you want to have in the list, and then call toList when you're done... or just use the built-in factory methods that do exactly that.
As the default List in Scala is immutable, the right way to add an element is to return a new list with the new element plus the older elements.
As a matter of fact, List has two methods, among others:
+:
++
The first one takes an element, add it as the first element and the rest of the list as it's tail and then returns the resulting list.
The other one takes another "collection" as parameter and adds it to the first list at the start.
List has another methods for adding the new element as the last one.
In Scala, these operations are permitted but take into consideration that always a new instance will be retrieved with the requested modifications as all objects are immutable by default.
As for your code goes, you could try with something like this:
object MyApplication extends App {
val numberOfPersons: Int = 10
val listOfPersons: List[Person] = makeListOfPersons(numberOfPersons)
def makeListOfPersons( numberOfPersons : Int ) : List[Person] = {
(1 to numberOfPersons).foldLeft(List.empty[Person]){ (accum, elem) =>
new Person() :: accum
}
}
}
(1 to numberOfPersons) creates a range, which could be seen as a List of ints, which will be traversed by foldLeft. This method will iterate through that list, and receives a seed, in this case an empty list of Person. Then, for every element in the int's list, a new Person is created and add to the list, returned as is the last expression and used the accumulator for the next iteration. Finally, a list of ten instances of Person is retrieved.
There are 5 ways to create List in scala:
Lisp style:
val list = 1::2::3::Nil
this style can also be thought of as a Haskell or functional programming (FP) style.
Java Style:
val list = List(1,2,3)
Scala List with range method
List.range(1, 10)
Create scala List with fill
List.fill(3)(5)
Scala List with tabulate
List.tabulate(5)(n => n * n)
element of the list are created according to the function we supply.
for more info please read this :
Preferred way to create a Scala list
I have a Set which incorporates a combination of strings, and subSets of strings, like so:
val s = Set(brand1-_test, Set(brand-one, brand_one, brandone), brands-two, brandthree1, Set(brand-three2, brand_three2, brandthree2))
How do I flatten this so that I have one flat set of strings? s.flatten doesn't work with the following error:
error: No implicit view available from Object => scala.collection.GenTraversableOnce[B]
Neither does flatMap. What am I missing here? The Set could just as easily incorporate a subLists or subArrays (they are the result of a previous function), if that makes a difference.
s.flatMap { case x:Iterable[_] => x; case y => Seq(y) }
Try putting it in a REPL:
scala> val s = Set("s1", Set("s2", "s3"))
s: scala.collection.immutable.Set[Object] = Set(s1, Set(s2, s3))
since you are providing two types (Set and String) then scala infers a type which covers both (Object in this case, but probably Any or AnyRef in most cases) which is not a collection and therefore cannot be flattened.
Let's say you have the following:
case class Foo(x: Int, y: Int) extends Ordered[Foo] {
override def compare(that: Foo): Int = x compareTo that.x
}
val mutableSet: scala.collection.mutable.SortedSet[Foo] =
scala.collection.mutable.SortedSet(Foo(1, 2), Foo(1,3))
I expect the result of mutableSet.size to be 2. Why, Foo(1,2) and Foo(1,3) are not equal but they have the same ordering. So the sorted set should be (IMO) Foo(1,2), Foo(1,3). As this is the order they were created in (even the other way around would be fine, counter intuitive but fine).
However, the result of mutableSet.size is 1 and it saves the last value i.e. Foo(1,3).
What am I missing?
The behavior is similar to the Java SortedSet collections. SortedSet uses compareTo in order to define equality, thus it eliminates the same Foo case classes from your example.
In Scala 2.11 it uses scala.collection.TreeSet for the implementation SortedSet implementation. The best way to figure out this is to put breakpoint into your compareTo method.
TreeSet is implemented using AVL Tree data structure, you can inspect the behavior by looking into the AVLTree.scala insert method of the Node class. It compare compareTo result with 0 in order to figure out does it duplicated element in the collection.
You have overridden compare so that only the first field is used in comparison. The Set uses this compare function not just to sort the items but also to determine if the items are equal for the purpose of storing them in the Set.
I know that when you type:
val list = List(2,3)
you are accessing the apply method of the List object which returns a List. What I can't understand is why is this possible when the List class is abstract and therefore cannot be directly instanciated(new List() won't compile)?
I'd also like to ask what is the difference between:
val arr = Array(4,5,6)
and
val arr = new Array(4, 5, 6)
The List class is sealed and abstract. It has two concreate implementations
Nil which represents an empty list
::[B] which represents a non empty list with head and tail. ::[B] in the documentation
When you call List.apply it will jump through some hoops and supply you with an instance of the ::[B] case class.
About array: new Array(4, 5, 6) will throw a compile error as the constructor of array is defined like this: new Array(_length: Int). The apply method of the Array companion object uses the arguments to create a new instance of an Array (with the help of ArrayBuilder).
I started writing that the easy way to determine this is to look at the sources for the methods you're calling, which are available from the ScalaDoc. However, the various levels of indirection that are gone through to actually build a list give lie to the term 'easy'! It's worth having a look through if you want, starting from the apply method in the List object which is defined as follows:
override def apply[A](xs: A*): List[A] = xs.toList
You may or may not know that a parameter of the form xs : A* is treated internally as a Seq, which means that we're calling the toList method on a Seq, which is defined in TraversableOnce. This then delegates to a generic to method, which looks for an implicit
CanBuildFrom which actually constructs the list. So what you're getting back is some implementation of List which is chosen by the CanBuildFrom. What you actually get is a scala.collection.immutable.$colon$colon, which implements a singly-linked list.
Luckily, the behaviour of Array.apply is a little easier to look up:
def apply[T: ClassTag](xs: T*): Array[T] = {
val array = new Array[T](xs.length)
var i = 0
for (x <- xs.iterator) { array(i) = x; i += 1 }
array
}
So, Array.apply just delegates to new Array and then sets elements appropriately.