Related
val l1 = List(1, 2, 3)
val l2 = List('a', 'b', 'c')
val tupleList = l1.zip(l2)
// List((1,a), (2,b), (3,c))
val objectList = l1.zip(l2).map(tuple => new MyObject(tuple._1, tuple._2))
// List(MyObject#7e1a1da6, MyObject#5f7f2382, MyObject#407cf41)
After writing this code, I feel like the map(tuple => new MyObject(tuple._1, tuple._2)) part looks a little dirty for two reasons:
I shouldn't be creating the tuples just to discard them in favor of MyObject. Why not just zip l1 and l2 into a list of MyObject in the first place?
tuple._1 and tuple._2 don't have any semantics. It can take some mental gymnastics to make sure I'm giving the Int as the first parameter and the Char as the second.
Is it possible to zip two Lists into my own object?
How can I make the MyObject construction above more semantically clear?
scala> case class Foo(i: Int, c: Char)
defined class Foo
scala> val f = Foo.apply _
f: (Int, Char) => Foo = <function2>
scala> (l1, l2).zipped map f
res12: List[Foo] = List(Foo(1,a), Foo(2,b), Foo(3,c))
More info, since someone didn't get what I meant, here's what this map looks like:
https://github.com/scala/scala/blob/2.11.x/src/library/scala/runtime/Tuple2Zipped.scala#L35
If you want a self made implementation for your problem, you can do something similar to what I did below. (wasted my time with)
There is already one implemented method to do that, which is described in #som-snytt 's answer.
An example implementation for your problem, which does not create intermediate tuples.
def createObjects[A,B,C](func: (A,B) => C)(l1: List[A], l2: List[B]) = {
val resultBuffer = new ListBuffer[C]
#tailrec
def loop(l1: List[A], l2: List[B]): Unit = l1 match {
case head :: tail if l2.headOption.isDefined => {
resultBuffer += func(l1.head, l2.head)
loop(l1.tail, l2.tail)
}
case Nil =>
}
loop(l1, l2)
resultBuffer.result
}
You can then use it like this:
createObjects(MyObject)(l1, l2)
createObjects(MyObject)(l1, l2) only works if MyObject is a case class or has an apply method.
In the other case you can do one of the following:
createObjects[Int, Char, MyObject](new MyObject(_,_))(l1, l2)
createObjects((i: Int, c: Char) => new MyObject(i,c))(l1, l2)
A slightly cleaner version using pattern matching would help with #2:
val objectList = (l1 zip l2).map { case (a, b) => new MyObject(a,b) }
A more extreme version would be to use a factory method on a companion class that turned the tuple into an instance of MyClass.
object MyClass {
def make(t: (Int, Char)) = new MyClass(t._1, t._2)
}
val objs = (l1 zip l2).map(MyClass.make)
You could even get fancier by making the companion object a function to further reduce the clutter:
object MyClass extends (Tuple2[Int, Char] => MyClass) {
def apply(t: (Int, Char)) = new MyClass(t._1, t._2)
}
val objs = (l1 zip l2).map(MyClass)
I am new to Scala and am a bit confused.
Given a list of lists List[List[Int]], how can one call a specific index of an element of each list, for example the second element of each list?
Simple:
val ints = List( List(1,2), List(3,4) )
val result = ints.map( l => l(1) )
This will produce (2,4).
While both of the other answers work, here is another version that is both safe to use and not complex. You can lift a Seq to a Function[Int, Option[A]] to make apply return Options instead of throwing exceptions. In Addition you can use flatMap instead of map{...}.flatten
List(List(1), List(1,2), List(1,2,3)).flatMap { xs =>
xs.lift(1)
}
// res1: List[Int] = List(2, 2)
Maybe this might be easy to fix but can you help me out or guide me to a solution. I have a remove function that goes through a List of tuples "List[(String,Any)]" and im trying to replace the 1 index of the value with Nil when the list is being looped over.
But when I try to replace the current v with Nil, it say the v is assigned to "val". Now I understand that scala lists are immutable. So maybe this is what is going wrong?
I tried a Tail recursion implementation as will but when I get out of the def there is a type mismatch. ie: is unit but required: Option[Any]
// remove(k) removes one value v associated with key k
// from the dictionary, if any, and returns it as Some(v).
// It returns None if k is associated to no value.
def remove(key:String):Option[Any] = {
for((k,v) <- d){
if(k == key){
var temp:Option[Any] = Some(v)
v = Nil
return temp
}
}; None
}
Here was the other way of trying to figure out
def remove(key:String):Option[Any] = {
def removeHelper(l:List[(String,Any)]):List[(String,Any)] =
l match {
case Nil => Nil
case (k,v)::t => if (key == k) t else (k,v)::removeHelper(t)
}
d = removeHelper(d)
}
Any Suggestions? This is a homework/Project for school thought I might add that for the people that don't like to help with homework.
Well, there are many ways of answering that question. I'll be outlining the ones I can think of here with my own implementations, but the list is by no means exhaustive (nor, probably, the implementations optimal).
First, you can try with existing combinators - the usual suspects are map, flatMap, foldLeft and foldRight:
def remove_flatMap(key: String, list: List[(String, Any)]): List[(String, Any)] =
// The Java developer in me rebels against creating that many "useless" instances.
list.flatMap {a => if(a._1 == key) Nil else List(a)}
def remove_foldLeft(key: String, list: List[(String, Any)]): List[(String, Any)] =
list.foldLeft(List[(String, Any)]()) {(acc, a) =>
if(a._1 == key) acc
else a :: acc
// Note the call to reverse here.
}.reverse
// This is more obviously correct than the foldLeft version, but is not tail-recursive.
def remove_foldRight(key: String, list: List[(String, Any)]): List[(String, Any)] =
list.foldRight(List[(String, Any)]()) {(a, acc) =>
if(a._1 == key) acc
else a :: acc
}
The problem with these is that, as far as I'm aware, you cannot stop them once a certain condition has been reached: I don't think they solve your problem directly, since they remove all instances of key rather than the first.
You also want to note that:
foldLeft must reverse the list once it's done, since it appends elements in the "wrong" order.
foldRight doesn't have that flaw, but is not tail recursive: it will cause memory issues on large lists.
map cannot be used for your problem, since it only lets us modify a list's values but not its structure.
You can also use your own implementation. I've included two versions, one that is tail-recursive and one that is not. The tail-recursive one is obviously the better one, but is also more verbose (I blame the ugliness of using a List[(String, Any)] rather than Map[String, Any]:
def remove_nonTailRec(key: String, list: List[(String, Any)]): List[(String, Any)] = list match {
case h :: t if h._1 == key => t
// This line is the reason our function is not tail-recursive.
case h :: t => h :: remove_nonTailRec(key, t)
case Nil => Nil
}
def remove_tailRec(key: String, list: List[(String, Any)]): List[(String, Any)] = {
#scala.annotation.tailrec
def run(list: List[(String, Any)], acc: List[(String, Any)]): List[(String, Any)] = list match {
// We've been aggregating in the "wrong" order again...
case h :: t if h._1 == key => acc.reverse ::: t
case h :: t => run(t, h :: acc)
case Nil => acc.reverse
}
run(list, Nil)
}
The better solution is of course to use the right tool for the job: a Map[String, Any].
Note that I do not think I answer your question fully: my examples remove key, while you want to set it to Nil. Since this is your homework, I'll let you figure out how to change my code to match your requirements.
List is the wrong collection to use if any key should only exist once. You should be using Map[String,Any]. With a list,
You have to do extra work to prevent duplicate entries.
Retrieval of a key will be slower, the further down the list it appears. Attempting to retrieve a non-existent key will be slow in proportion to the size of the list.
I guess point 2 is maybe why you are trying to replace it with Nil rather than just removing the key from the list. Nil is not the right thing to use here, really. You are going to get different things back if you try and retrieve a non-existent key compared to one that has been removed. Is that really what you want? How much sense does it make to return Some(Nil), ever?
Here's a couple of approaches which work with mutable or immutable lists, but which don't assume that you successfully stopped duplicates creeping in...
val l1: List[(String, Any)] = List(("apple", 1), ("pear", "violin"), ("banana", Unit))
val l2: List[(Int, Any)] = List((3, 1), (4, "violin"), (7, Unit))
def remove[A,B](key: A, xs: List[(A,B)]) = (
xs collect { case x if x._1 == key => x._2 },
xs map { case x if x._1 != key => x; case _ => (key, Nil) }
)
scala> remove("apple", l1)
res0: (List[(String, Any)], List[(String, Any)]) = (List((1)),List((apple, List()),(pear,violin), (banana,object scala.Unit)))
scala> remove(4, l2)
res1: (List[(Int, Any)], List[(Int, Any)]) = (List((violin)),List((3,1), (4, List()), (7,object scala.Unit)))
scala> remove("snark", l1)
res2: (List[Any], List[(String, Any)]) = (List(),List((apple,1), (pear,violin), (banana,object scala.Unit)))
That returns a list of matching values (so an empty list rather than None if no match) and the remaining list, in a tuple. If you want a version that just completely removes the unwanted key, do this...
def remove[A,B](key: A, xs: List[(A,B)]) = (
xs collect { case x if x._1 == key => x._2 },
xs filter { _._1 != key }
)
But also look at this:
scala> l1 groupBy {
case (k, _) if k == "apple" => "removed",
case _ => "kept"
}
res3: scala.collection.immutable.Map[String,List[(String, Any)]] = Map(removed -> List((apple,1)), kept -> List((pear,violin), (banana,object scala.Unit)))
That is something you could develop a bit. All you need to do is add ("apple", Nil) to the "kept" list and extract the value(s) from the "removed" list.
Note that I am using the List combinator functions rather than writing my own recursive code; this usually makes for clearer code and is often as fast or faster than a hand-rolled recursive function.
Note also that I don't change the original list. This means my function works with both mutable and immutable lists. If you have a mutable list, feel free to assign my returned list as the new value for your mutable var. Win, win.
But please use a map for this. Look how simple things become:
val m1: Map[String, Any] = Map(("apple", 1), ("pear", "violin"), ("banana", Unit))
val m2: Map[Int, Any] = Map((3, 1), (4, "violin"), (7, Unit))
def remove[A,B](key: A, m: Map[A,B]) = (m.get(key), m - key)
scala> remove("apple", m1)
res0: (Option[Any], scala.collection.immutable.Map[String,Any]) = (Some(1),Map(pear -> violin, banana -> object scala.Unit))
scala> remove(4, m2)
res1: (Option[Any], scala.collection.immutable.Map[Int,Any]) = (Some(violin),Map(3 -> 1, 7 -> object scala.Unit))
scala> remove("snark", m1)
res2: res26: (Option[Any], scala.collection.immutable.Map[String,Any]) = (None,Map(apple -> 1, pear -> violin, banana -> object scala.Unit))
The combinator functions make things easier, but when you use the right collection, it becomes so easy that it is hardly worth writing a special function. Unless, of course, you are trying to hide the data structure - in which case you should really be hiding it inside an object.
What is the best way to remove the first occurrence of an object from a list in Scala?
Coming from Java, I'm accustomed to having a List.remove(Object o) method that removes the first occurrence of an element from a list. Now that I'm working in Scala, I would expect the method to return a new immutable List instead of mutating a given list. I might also expect the remove() method to take a predicate instead of an object. Taken together, I would expect to find a method like this:
/**
* Removes the first element of the given list that matches the given
* predicate, if any. To remove a specific object <code>x</code> from
* the list, use <code>(_ == x)</code> as the predicate.
*
* #param toRemove
* a predicate indicating which element to remove
* #return a new list with the selected object removed, or the same
* list if no objects satisfy the given predicate
*/
def removeFirst(toRemove: E => Boolean): List[E]
Of course, I can implement this method myself several different ways, but none of them jump out at me as being obviously the best. I would rather not convert my list to a Java list (or even to a Scala mutable list) and back again, although that would certainly work. I could use List.indexWhere(p: (A) ⇒ Boolean):
def removeFirst[E](list: List[E], toRemove: (E) => Boolean): List[E] = {
val i = list.indexWhere(toRemove)
if (i == -1)
list
else
list.slice(0, i) ++ list.slice(i+1, list.size)
}
However, using indices with linked lists is usually not the most efficient way to go.
I can write a more efficient method like this:
def removeFirst[T](list: List[T], toRemove: (T) => Boolean): List[T] = {
def search(toProcess: List[T], processed: List[T]): List[T] =
toProcess match {
case Nil => list
case head :: tail =>
if (toRemove(head))
processed.reverse ++ tail
else
search(tail, head :: processed)
}
search(list, Nil)
}
Still, that's not exactly succinct. It seems strange that there's not an existing method that would let me do this efficiently and succinctly. So, am I missing something, or is my last solution really as good as it gets?
You can clean up the code a bit with span.
scala> def removeFirst[T](list: List[T])(pred: (T) => Boolean): List[T] = {
| val (before, atAndAfter) = list span (x => !pred(x))
| before ::: atAndAfter.drop(1)
| }
removeFirst: [T](list: List[T])(pred: T => Boolean)List[T]
scala> removeFirst(List(1, 2, 3, 4, 3, 4)) { _ == 3 }
res1: List[Int] = List(1, 2, 4, 3, 4)
The Scala Collections API overview is a great place to learn about some of the lesser known methods.
This is a case where a little bit of mutability goes a long way:
def withoutFirst[A](xs: List[A])(p: A => Boolean) = {
var found = false
xs.filter(x => found || !p(x) || { found=true; false })
}
This is easily generalized to dropping the first n items matching the predicate. (i<1 || { i = i-1; false })
You can also write the filter yourself, though at this point you're almost certainly better off using span since this version will overflow the stack if the list is long:
def withoutFirst[A](xs: List[A])(p: A => Boolean): List[A] = xs match {
case x :: rest => if (p(x)) rest else x :: withoutFirst(rest)(p)
case _ => Nil
}
and anything else is more complicated than span without any clear benefits.
is there an alternative 'List' syntax in Scala?
Is it possible to define one aditional class/type/operator* called '[' and ']'?
I know 'square brackets' are used to indicate Type, but they are perfect to the repetitive task of declaring lists.
A ';' or '?' would be good also, as a last resource.
Thanks
obs.:
after much search the only alternative I found was to use 'cons':
val list = 1 :: 2 :: 3 :: Nil
but it doesn't reduce any key typing at all.
I am still learning those things in Scala
EDIT:
Just to clarify: Performance is not a priority in my case. And yes, shift is not welcome. :P
Motivation behind the scenes: I like Haskell style, but cannot use it directly with Java.
EDIT 2:
Final solution based on both Rex Kerr solutions
implementing object Types:
package a
object Types {
type \[z] = List[z]
implicit def make_lists[A](z: A) = new ListMaker(z)
class ListMaker[A](a0: A) {
private[this] val buffer = List.newBuilder[A]
buffer += a0
def \(z: A) = {
buffer += z;
this
}
def \\ = buffer.result
}
}
using object Types:
package a
import a.Types._
object Whatever {
def listInListOut (l: \[Int]) = {
1\2\\
}
}
[ and ] are reserved symbols in Scala which are used for type annotations. You can't use them for lists. ; is reserved for end of line. You could use ? in many cases, but it would be awkward.
I recommend that you learn to use the :: notation (and get used to typing the : symbol fast twice in succession) because it really makes the list operations visually clear, plus it is a great syntactic reminder that lists are weird because you put things on the head of the list.
However, if you cannot tolerate this, your best option is probably to define a one-letter list symbol. For example,
List(1,2,3,4)
is a list of the numbers from 1 to 4. What if you could just type L instead of List? It turns out that you can, since this is not a fancy constructor or static method, but a singleton companion object to the class List. So you just
val L = List
L(1,2,3,4)
and you are just one character worse off than your suggestion of brackets.
Define
def l[A](a:A*) = List(a:_*)
Then you can do
l(1,2,3)
which is only one character more than [1,2,3]
I can't help pointing out another way to go here for lists where all the elements are the same type, if you really hate the shift key and don't care if other people can understand your code:
class ListMaker[A](a0: A) {
private[this] val buffer = List.newBuilder[A]
buffer += a0
def \(a: A) = { buffer += a; this }
def \\ = buffer.result
}
implicit def make_lists[A](a: A) = new ListMaker(a)
Now you can list to your heart's content, without ever touching the shift key!
scala> val a = 1\2\3\4\5\\
a: List[Int] = List(1, 2, 3, 4, 5)
scala> val b = 'a'\'b'\\
b: List[Char] = List(a, b)
scala> val c = false\true\false\false\false\false\true\\
c: List[Boolean] = List(false, true, false, false, false, false, true)
This uses exactly as many characters as brackets would. (It doesn't nest well, however.)
Welcome to Scala version 2.10.0.r24777-b20110419020105 (Java HotSpot(TM) Client VM, Java 1.6.0
Type in expressions to have them evaluated.
Type :help for more information.
scala> class LM[A](x: A) {
| def \(y: A) = List(x,y)
| }
defined class LM
scala> implicit def a2l[A](x: A): LM[A] = new LM(x)
a2l: [A](x: A)LM[A]
scala> class LX[A](xs: List[A]) {
| def \(y: A) = xs:::List(y)
| }
defined class LX
scala> implicit def l2lx[A](xs: List[A]): LX[A] = new LX(xs)
l2lx: [A](xs: List[A])LX[A]
scala> 1\2
res0: List[Int] = List(1, 2)
scala> 1\2\3
res1: List[Int] = List(1, 2, 3)
scala>
Not exactly an alternative syntax, but it is by far the most portable solution:
In Intellij IDEA it is possible to create "Live Templates";
press Ctrl+Alt+s; search for "template"; go to "Live Templates" section;
just add one new item named "l" inside Scala entry, add a random description and the following code:
List($END$)
Press Enter, go to the editor, press L followed by Tab.
It is the end of your typing pains.
Do the same for Arrays.