Related
I need to create a new instance of BitSet class from another BitSet object (input).
I expected something like new BitSet(input), but none found. I could get the new instance with map() method as follows, but I don't think this is the best solution.
var r = input.map(_ + 0)(BitSet.canBuildFrom)
What's the copy constructor of BitSet? What's the general rule for copy constructor in Scala?
You can create another with the bitmask of the first:
var r = new BitSet(input.toBitMask)
I think, the general rule is to use immutable collections. They are, well, immutable, so you can pass them around freely without taking special care for copying them.
When you need mutable collections, however, copying collections becomes useful. I discovered that using standard to method works:
scala> mutable.Set(1, 2, 3)
res0: scala.collection.mutable.Set[Int] = Set(1, 2, 3)
scala> res0.to[mutable.Set]
res1: scala.collection.mutable.Set[Int] = Set(1, 2, 3)
scala> res0 eq res1
res2: Boolean = false
However, it won't work with BitSet because it is not a generic collection, and to needs type constructor as its generic parameter. For BitSet you can use the method suggested by Lee. BTW, it is intended exactly for scala.collection.mutable.BitSet, because scala.collection.immutable.BitSet does not contain such constructor (nor does it need it).
The "copy" method on collections is called clone (to be consistent with Java style).
scala> collection.mutable.BitSet(1,2,3)
res0: scala.collection.mutable.BitSet = BitSet(1, 2, 3)
scala> res0.clone
res1: scala.collection.mutable.BitSet = BitSet(1, 2, 3)
scala> res0 += 4
res2: res0.type = BitSet(1, 2, 3, 4)
scala> res1
res40: scala.collection.mutable.BitSet = BitSet(1, 2, 3)
I called tail on an Array, but saw a warning.
scala> val arr = Array(1,2)
arr: Array[Int] = Array(1, 2)
scala> arr tail
warning: there were 1 feature warning(s); re-run with -feature for details
res3: Array[Int] = Array(2)
Scaladocs for Array shows an UnsupportedOperationException [will be thrown]
if the mutable indexed sequence is empty.
Is there a safe, won't throw exception, way to get the tail of an array?
Is there a safe, won't throw exception, way to get the tail of an
array?
You can use drop:
scala> Array(1, 2, 3).drop(1)
res0: Array[Int] = Array(2, 3)
scala> Array[Int]().drop(1)
res1: Array[Int] = Array()
Also note that as mentioned by #TravisBrown in the comment below, drop doesn't differentiate between an empty tail (for collections with one element) and the absence of tail (for empty collections) since in both the cases, drop(1) would return an empty collection.
First of all, the warning doesn't have anything to do with the fact that you're using an unsafe method. If you restart the REPL with -feature you'll see the following:
scala> arr tail
<console>:9: warning: postfix operator tail should be enabled
by making the implicit value language.postfixOps visible...
And a pointer to the documentation for scala.language.postfixOps, which includes the following note:
Postfix operators interact poorly with semicolon inference. Most programmers avoid them for this reason.
This is good advice. Being able to write arr tail instead of arr.tail isn't worth the fuss.
Now about the safety issue. The standard library doesn't provide a tailOption for collections, but you can get the same effect using headOption and map:
scala> val arr = Array(1, 2)
arr: Array[Int] = Array(1, 2)
scala> arr.headOption.map(_ => arr.tail)
res0: Option[Array[Int]] = Some([I#359be9fb)
If this is too verbose or opaque or inefficient for you, you can easily create an implicit class that would add a nicer tailOption to Array (or Seq, or IndexedSeq, etc.).
See #TravisBrown's answer for the reason of your warning.
I would personally use a scala.util.Try rather than his rather clever map on the array's head:
scala> val arr = Array(0, 1, 2)
arr: Array[Int] = Array(0, 1, 2)
scala> scala.util.Try {arr.tail} foreach {t => println(t.mkString(","))}
1,2
Is there a quick scala idiom to have retrieve multiple elements of a a traversable using indices.
I am looking for something like
val L=1 to 4 toList
L(List(1,2)) //doesn't work
I have been using map so far, but wondering if there was a more "scala" way
List(1,2) map {L(_)}
Thanks in advance
Since a List is a Function you can write just
List(1,2) map L
Although, if you're going to be looking things up by index, you should probably use an IndexedSeq like Vector instead of a List.
You could add an implicit class that adds the functionality:
implicit class RichIndexedSeq[T](seq: IndexedSeq[T]) {
def apply(i0: Int, i1: Int, is: Int*): Seq[T] = (i0+:i1+:is) map seq
}
You can then use the sequence's apply method with one index or multiple indices:
scala> val data = Vector(1,2,3,4,5)
data: scala.collection.immutable.Vector[Int] = Vector(1, 2, 3, 4, 5)
scala> data(0)
res0: Int = 1
scala> data(0,2,4)
res1: Seq[Int] = ArrayBuffer(1, 3, 5)
You can do it with a for comprehension but it's no clearer than the code you have using map.
scala> val indices = List(1,2)
indices: List[Int] = List(1, 2)
scala> for (index <- indices) yield L(index)
res0: List[Int] = List(2, 3)
I think the most readable would be to implement your own function takeIndices(indices: List[Int]) that takes a list of indices and returns the values of a given List at those indices. e.g.
L.takeIndices(List(1,2))
List[Int] = List(2,3)
Concerning the yield command in Scala and the following example:
val values = Set(1, 2, 3)
val results = for {v <- values} yield (v * 2)
Can anyone explain how Scala knows which type of collection to yield into? I know it is based on values, but how would I go about writing code that replicates yield?
Is there any way for me to change the type of the collection to yield into? In the example I want results to be of type List instead of Set.
Failing this, what is the best way to convert from one collection to another? I know about _:*, but as a Set is not a Seq this does not work. The best I could find thus far is val listResults = List() ++ results.
Ps. I know the example does not following the recommended functional way (which would be to use map), but it is just an example.
The for comprehensions are translated by compiler to map/flatMap/filter calls using this scheme.
This excellent answer by Daniel answers your first question.
To change the type of result collection, you can use collection.breakout (also explained in the post I linked above.)
scala> val xs = Set(1, 2, 3)
xs: scala.collection.immutable.Set[Int] = Set(1, 2, 3)
scala> val ys: List[Int] = (for(x <- xs) yield 2 * x)(collection.breakOut)
ys: List[Int] = List(2, 4, 6)
You can convert a Set to a List using one of following ways:
scala> List.empty[Int] ++ xs
res0: List[Int] = List(1, 2, 3)
scala> xs.toList
res1: List[Int] = List(1, 2, 3)
Recommended read: The Architecture of Scala Collections
If you use map/flatmap/filter instead of for comprehensions, you can use scala.collection.breakOut to create a different type of collection:
scala> val result:List[Int] = values.map(2*)(scala.collection.breakOut)
result: List[Int] = List(2, 4, 6)
If you wanted to build your own collection classes (which is the closest thing to "replicating yield" that makes any sense to me), you should have a look at this tutorial.
Try this:
val values = Set(1, 2, 3)
val results = for {v <- values} yield (v * 2).toList
I wanted to add items dynamically into an array. But it seems Scala arrays and lists don't provide any methods for adding items dynamically due to the immutable nature.
So I decided to use List data type to make use of this :: method to achieve this. My code look like this
var outList = List(Nil)
val strArray = Array("ram","sam","bam")
for (str<-strArray)
outList = str :: outList
Though it works in some way, the problem is the new strings are pre-appended into the list. But the ideal requirement is order of the data. Yeah, I know what you are thinking, you can reverse the final result list to get the original order. But the problem is it's a huge array. And I believe it's not a solution though it solves the problem. I believe there should be a simple way to solve this...
And my reason for hacking Scala is to learn the functional way of coding. Having var (mutable type) and populating the list on the fly seems to me is not a functional way of solving things.
How can I do it?
Ideally, I want to achieve something like this in Scala (below the C# code)
List<int> ls = new List<int>();
for (int i = 0; i < 100; i++)
ls.Add(i);
But it seems Scala Arrays & Lists doesn't provide any methods for adding items dynamically due to the immutable nature.
Well, no. Scala Arrays are just Java arrays, so they are mutable:
val arr = Array(1,2)
arr(0) = 3 // arr == Array(3, 2)
But just as Java (and C/C++/C#/etc.) arrays, you can't change the size of an array.
So you need another collection, which is backed by an array, but does allow resizing. A suitable collection in Scala is scala.collection.mutable.ArrayBuffer, java.util.ArrayList in Java, etc.
If you want to get a List instead of an Array in the end, use scala.collection.mutable.ListBuffer instead.
Going after retronym's answer:
If you still want to use list there are a few ways to prepend an item to the list. What you can do is (yes the top part is still wrong):
scala> var outList : List[String] = Nil
outList: List[String] = List()
scala> val strArray = Array("a","b","c")
strArray: Array[java.lang.String] = Array(a, b, c)
scala> for(s <- strArray)
| outList = outList :+ s
scala> outList
res2: List[String] = List(a, b, c)
Note the :+ operator. If you rather append, you'd use s +: outList.
Now who says programming in Scala isn't fun? ;)
P.S. Maybe the reason why you'd want to make them immutable is the speed. Handling large data will be more efficient with immutable data types. Am I right?
If you want to use a mutable Buffer, as retronym mentioned. It looks like this:
scala> var outList = scala.collection.mutable.Buffer[String]()
outList: scala.collection.mutable.Buffer[String] = ArrayBuffer()
scala> for(str<-strArray) outList += str
scala> outList
res10: scala.collection.mutable.ListBuffer[String] = ListBuffer(ram, sam, bam)
Anyway, perhaps it is better to directly do the things you want to do with the strArray. E.g:
strArray map(_.toUpperCase) foreach(println)
If you want to work with immutable structures, you can use the ++ method:
scala> val orgList = List(1,2,3)
orgList: List[Int] = List(1, 2, 3)
scala> val list2Add = List(4,5,6)
list2Add: List[Int] = List(4, 5, 6)
scala> val newList = orgList ++ list2Add
newList: List[Int] = List(1, 2, 3, 4, 5, 6)
If you want to do more work on the elements than just adding them you can use higher order functions:
val newList = orgList ++ list2Add.map(_ * 2)
newList: List[Int] = List(1, 2, 3, 8, 10, 12)
Or with a for loop:
val newList = orgList ++ {for(x <- list2Add) yield 2*x}
Or you could create some recursive loop:
def addAll(toList: List[Int], fromList: List[Int]): List[Int] =
fromList match {
case x :: tail => addAll(2*x :: toList, tail)
case Nil => toList
}
val newList = addAll(orgList, list2Add )
but in this case the ordering of the added elements will be in reversed:
List(12, 10, 8, 1, 2, 3)
If you want performance when working with lists, it is better to reverse the result than try to add new elements in the end. Adding elements in the end to a list is nooot good :-)
Okay, there are a few things to clear up.
This is wrong, you're make a one element list, containing an empty list:
scala> var outList = List(Nil)
outList: List[object Nil] = List(List())
Nil is the empty list:
scala> var outList: List[String] = Nil
outList: List[String] = List()
Or, if you prefer:
scala> var outList = List[String]()
outList: List[String] = List()
Without more context, it's hard to know what you mean by 'dynamically'. Your example code would be better written as:
scala> val strArray = Array("ram","sam","bam")
strArray: Array[java.lang.String] = Array(ram, sam, bam)
scala> strArray toList
res0: List[java.lang.String] = List(ram, sam, bam)
If you want a mutable collection that can grow and efficiently handle prepend, append, and insert operations, you could use scala.mutable.Buffer.
If you are looking to create a new collection, you can use the yield key word:
val outlist = for(i <- 0 to 100) yield i
Or:
val arrList = "Some" :: "Input" :: "List" :: Nil
val outlist = for ( i <- arrList ) yield i
Technically, outlist is a Seq in both of the above examples so you may need to call the toList method on it if you need some of List's methods.
We can use ArrayBuffer as suggested.
However, i have created a simple program which takes no of parameters for an Array of int and it will let you enter the numbers and finally we are displaying them.
val arraySize = scala.io.StdIn.readLine().toInt
val arr = new ArrayBuffer[Int]() ++ (1 to arraySize).map{
i =>
scala.io.StdIn.readLine().toInt
}
println(arr.mkString(","))