Question is simple.
How to access a tuple by using Index variable in SML?
val index = 5;
val tuple1 = (1,2,3,4,5,6,7,8,9,10);
val correctValue = #index tuple1 ??
I hope, somebody would be able to help out.
Thanks in advance!
There doesn't exist a function which takes an integer value and a tuple, and extracts that element from the tuple. There are of course the #1, #2, ... functions, but these do not take an integer argument. That is, the name of the "function" is #5, it is not the function # applied to the value 5. As such, you cannot substitute the name index instead of the 5.
If you don't know in advance at which place in the tuple the element you want will be at, you're probably using them in a way they're not intended to be used.
You might want a list of values, for which the 'a list type is more natural. You can then access the nth element using List.nth.
To clarify a bit, why you can't do that you need some more knowledge of what a tuple is in SML.
Tuples are actually represented as records in SML. Remember that records has the form {id = expr, id = expr, ..., id = expr} where each identifier is a label.
The difference of tuples and records is given away by the way you index elements in a tuple: #1, #2, ... (1, "foo", 42.0) is a derived form of (equivalent with) {1 = 1, 2 = "foo", 3 = 42.0}. This is perhaps better seen by the type that SML/NJ gives that record
- {1 = 1, 2 = "foo", 3 = 42.0};
val it = (1,"foo",42.0) : int * string * real
Note the type is not shown as a record type such as {1: int, 2: string, 3: real}. The tuple type is again a derived form of the record type.
Actually #id is not a function, and thus it can't be called with a variable as "argument". It is actually a derived form of (note the wildcard pattern row, in the record pattern match)
fn {id=var, ...} => var
So in conclusion, you won't be able to do what you wan't, since these derived forms (or syntactic sugar if you will) aren't dynamic in any ways.
One way is as Sebastian Paaske said to use lists. The drawback is that you need O(n) computations to access the nth element of a list. If you need to access an element in O(1) time, you may use arrays, which are in basic sml library.
You can find ore about arrays at:
http://sml-family.org/Basis/array.html
Related
In OCaml, suppose I have a string list as follows:
let ls : string list = ["A"; "A"; "B"; "B"; "A"; "Y"; "Y"; "Y"] ;;
I'm having trouble writing a function that calculates how many times an element occurs consecutively and also pairs up that element with its frequency. For instance, given the above list as input, the function should return [("A", 2); ("B", 2), ("A", 1), ("Y", 3)].
I've tried looking for some hints elsewhere but almost all other similar operations are done using int lists, where it is easy to simply add numbers up. But here, we cannot add strings.
My intuition was to use something like fold_left in some similar fashion as below:
let lis : int list = [1;2;3;4;5]
let count (lis : int list) = List.fold_left (fun x y -> x + y) (0) (lis)
which is essentially summing all the elements cumulatively from left to right. But, in my case, I don't want to cumulatively sum all the elements, I just need to count how many times an element occurs consecutively. Some advice would be appreciated!
This is obviously a homework assignment, so I will just give a couple of hints.
When you get your code working, it won't be adding strings (or any other type) together. It will be adding ints together. So you might want to look back at those examples on the net again :-)
You can definitely use fold_left to get an answer. First, note that the resultl is a list of pairs. The first element of each pair can be any type, depending on the type of the original list. The second element in each pair is an int. So you have a basic type that you're working with: ('a * int) list.
Imagine that you have a way to "increment" such a list:
let increment (list: ('a * int) list) value =
(* This is one way to think of your problem *)
This function looks for the pair in the list whose first element is equal to value. If it finds it, it returns a new list where the associated int is one larger than before. If it doesn't find it, it returns a new list with an extra element (value, 1).
This is the basic operation you want to fold over your list, rather than the + operation of your example code.
Given a list, I would like to produce a second list of elements selected from the first one.
For example:
let l1 = [1..4]
let n = [0; 2]
l1.[n]
should return 1 and 3, the first and third element of l1.
Unfortunately, it returns an error:
error FS0001: This expression was expected to have type
int but here has type int list
Now, I wonder, does exist a way to pass an argument n representing a list or, even better, an expression?
F# doesn't offer syntactical support for that sort of indexing. You can ask for a continuous slice of an array like below, but it doesn't cover your exact scenario.
let a = [|1 .. 4|]
let b = a.[0..2]
// returns [|1; 2; 3|]
You can easily write a function for that though:
let slice<'a> (indices: int list) (arr: 'a array) =
[| for idx in indices do yield arr.[idx] |]
slice [0; 2] a
// returns [| 1; 3 |]
I'm leaving proper handling of out-of-bounds access as an exercise ;)
With indexed properties, you should be able to define this for your types: just define a member Item with get(indexes) which accepts a list/array. But standard lists and arrays already have Item defined, and you can't have two at once...
I solved it this way:
List.map (fun index -> l1.[index]) n
It's inefficient for large lists, but works for me.
I'm coding in haskell and want to know how find a certain element in mutiple list.
Here an example let say:
x = [(1,2,3,4,5),
(3,4,5,6,6),
(5,6,2,1,1),
(1,2,5,6,2)];
Let say I want to find the 3rd element of each list.
So the program will print out 4,6,1,6
I know about the !! but when I do something like x !! 3, it prints out the third row(1,2,5,6,2).
I want it so it print out the 3rd element of each list.
What you've provided is not actually a list of lists, but a list of tuples. Tuples have a special type based on the number and type of their elements, so the type of your x above is [(Int,Int,Int,Int,Int)].
Unlike lists, which allow us to extract values by index with the !! operator (ex. [1,2,3] !! 1 = 2), in order to extract specific values from a tuple we must pattern match the entire tuple, giving some name to the value we wish to extract and using it in our return value. To extract the fourth value from a tuple of holding 5 values, we could write a function like this:
f (a,b,c,d,e) = d
Or, as an anonymous function (because, if we are only going to use it when mapping over the list, it's nice to not bother assigning it a name):
(\(a,b,c,d,e) -> d)
Since we only care about the fourth value, we can choose to discard all others (you said third but meant index 3 -> 4th term above?):
(\(_,_,_,x,_) -> x)
Now we have a list of such tuples, and we'll want to apply it to each. We can do this with map, which will apply the function to each and return a list of the third value from each tuple:
f xs = map (\(_,_,_,x,_) -> x) xs
Or, with eta-reduction:
f = map (\(_,_,_,x,_) -> x)
Example usage:
gchi>> f [(1,2,3,4,5),(3,4,5,6,6),(5,6,2,1,1),(1,2,5,6,2)]
[4,6,1,6]
I have a map of key value pairs and I am trying to fetch the value given a key, however although it returns me a value it comes along with some, any idea how can I get rid of it?
My code is:
val jsonmap = simple.split(",\"").toList.map(x => x.split("\":")).map(x => Tuple2(x(0), x(1))).toMap
val text = jsonmap.get("text")
Where "text" is the key and I want the value that it is mapped to, I am currently getting the following output:
Some("4everevercom")
I tried using flatMap instead of Map but it doesn't work either
You are looking for the apply method. Seq, Set and Map implement different apply methods, the difference being the main distinction between each one.
As a syntactic sugar, .apply can be omitted in o.apply(x), so you'd just have to do this:
val text = jsonmap("text") // pass "key" to apply and receive "value"
For Seq, apply takes an index and return a value, as you used in your own example:
x(0), x(1)
For Set, apply takes a value, and returns a Boolean.
You can use getOrElse, as #Brian stated, or 'apply' method and deal with absent values on your own:
val text: String = jsonmap("text")
// would trow java.util.NoSuchElementException, if no key presented
Moreover, you can set some default value so Map can fallback to it, if no key found:
val funkyMap = jsonmap.get("text").withDefaultValue("")
funkyMap("foo")
// if foo or any other key is not presented in map, "" will be returned
Use it, if you want to have default value for all missing keys.
You can use getOrElse which gets the value of Some if there is one or the default value that you specify. If the key exists in the map, you will get the value from Some. If the key does not exist, you will get the value specified.
scala> val map = Map(0 -> "foo")
map: scala.collection.immutable.Map[Int,String] = Map(0 -> foo)
scala> map.get(0)
res3: Option[String] = Some(foo)
scala> map.getOrElse(1, "bar")
res4: String = bar
Also, see this for info on Scala's Some and None Options: http://www.codecommit.com/blog/scala/the-option-pattern
Just offering additional options that might help you work with Option and other similar structures you'll find in the standard library.
You can also iterate (map) over the Option. This works since Option is an Iterable containing either zero or one element.
myMap.get(key) map { value =>
// use value...
}
Equivalently, you can use a for if you feel it makes for clearer code:
for (value <- myMap.get(key)) {
// use value...
}
I've got a list of objects List[Object] which are all instantiated from the same class. This class has a field which must be unique Object.property. What is the cleanest way to iterate the list of objects and remove all objects(but the first) with the same property?
list.groupBy(_.property).map(_._2.head)
Explanation: The groupBy method accepts a function that converts an element to a key for grouping. _.property is just shorthand for elem: Object => elem.property (the compiler generates a unique name, something like x$1). So now we have a map Map[Property, List[Object]]. A Map[K,V] extends Traversable[(K,V)]. So it can be traversed like a list, but elements are a tuple. This is similar to Java's Map#entrySet(). The map method creates a new collection by iterating each element and applying a function to it. In this case the function is _._2.head which is shorthand for elem: (Property, List[Object]) => elem._2.head. _2 is just a method of Tuple that returns the second element. The second element is List[Object] and head returns the first element
To get the result to be a type you want:
import collection.breakOut
val l2: List[Object] = list.groupBy(_.property).map(_._2.head)(breakOut)
To explain briefly, map actually expects two arguments, a function and an object that is used to construct the result. In the first code snippet you don't see the second value because it is marked as implicit and so provided by the compiler from a list of predefined values in scope. The result is usually obtained from the mapped container. This is usually a good thing. map on List will return List, map on Array will return Array etc. In this case however, we want to express the container we want as result. This is where the breakOut method is used. It constructs a builder (the thing that builds results) by only looking at the desired result type. It is a generic method and the compiler infers its generic types because we explicitly typed l2 to be List[Object] or, to preserve order (assuming Object#property is of type Property):
list.foldRight((List[Object](), Set[Property]())) {
case (o, cum#(objects, props)) =>
if (props(o.property)) cum else (o :: objects, props + o.property))
}._1
foldRight is a method that accepts an initial result and a function that accepts an element and returns an updated result. The method iterates each element, updating the result according to applying the function to each element and returning the final result. We go from right to left (rather than left to right with foldLeft) because we are prepending to objects - this is O(1), but appending is O(N). Also observe the good styling here, we are using a pattern match to extract the elements.
In this case, the initial result is a pair (tuple) of an empty list and a set. The list is the result we're interested in and the set is used to keep track of what properties we already encountered. In each iteration we check if the set props already contains the property (in Scala, obj(x) is translated to obj.apply(x). In Set, the method apply is def apply(a: A): Boolean. That is, accepts an element and returns true / false if it exists or not). If the property exists (already encountered), the result is returned as-is. Otherwise the result is updated to contain the object (o :: objects) and the property is recorded (props + o.property)
Update: #andreypopp wanted a generic method:
import scala.collection.IterableLike
import scala.collection.generic.CanBuildFrom
class RichCollection[A, Repr](xs: IterableLike[A, Repr]){
def distinctBy[B, That](f: A => B)(implicit cbf: CanBuildFrom[Repr, A, That]) = {
val builder = cbf(xs.repr)
val i = xs.iterator
var set = Set[B]()
while (i.hasNext) {
val o = i.next
val b = f(o)
if (!set(b)) {
set += b
builder += o
}
}
builder.result
}
}
implicit def toRich[A, Repr](xs: IterableLike[A, Repr]) = new RichCollection(xs)
to use:
scala> list.distinctBy(_.property)
res7: List[Obj] = List(Obj(1), Obj(2), Obj(3))
Also note that this is pretty efficient as we are using a builder. If you have really large lists, you may want to use a mutable HashSet instead of a regular set and benchmark the performance.
Starting Scala 2.13, most collections are now provided with a distinctBy method which returns all elements of the sequence ignoring the duplicates after applying a given transforming function:
list.distinctBy(_.property)
For instance:
List(("a", 2), ("b", 2), ("a", 5)).distinctBy(_._1) // List((a,2), (b,2))
List(("a", 2.7), ("b", 2.1), ("a", 5.4)).distinctBy(_._2.floor) // List((a,2.7), (a,5.4))
Here is a little bit sneaky but fast solution that preserves order:
list.filterNot{ var set = Set[Property]()
obj => val b = set(obj.property); set += obj.property; b}
Although it uses internally a var, I think it is easier to understand and to read than the foldLeft-solution.
A lot of good answers above. However, distinctBy is already in Scala, but in a not-so-obvious place. Perhaps you can use it like
def distinctBy[A, B](xs: List[A])(f: A => B): List[A] =
scala.reflect.internal.util.Collections.distinctBy(xs)(f)
With preserve order:
def distinctBy[L, E](list: List[L])(f: L => E): List[L] =
list.foldLeft((Vector.empty[L], Set.empty[E])) {
case ((acc, set), item) =>
val key = f(item)
if (set.contains(key)) (acc, set)
else (acc :+ item, set + key)
}._1.toList
distinctBy(list)(_.property)
One more solution
#tailrec
def collectUnique(l: List[Object], s: Set[Property], u: List[Object]): List[Object] = l match {
case Nil => u.reverse
case (h :: t) =>
if (s(h.property)) collectUnique(t, s, u) else collectUnique(t, s + h.prop, h :: u)
}
I found a way to make it work with groupBy, with one intermediary step:
def distinctBy[T, P, From[X] <: TraversableLike[X, From[X]]](collection: From[T])(property: T => P): From[T] = {
val uniqueValues: Set[T] = collection.groupBy(property).map(_._2.head)(breakOut)
collection.filter(uniqueValues)
}
Use it like this:
scala> distinctBy(List(redVolvo, bluePrius, redLeon))(_.color)
res0: List[Car] = List(redVolvo, bluePrius)
Similar to IttayD's first solution, but it filters the original collection based on the set of unique values. If my expectations are correct, this does three traversals: one for groupBy, one for map and one for filter. It maintains the ordering of the original collection, but does not necessarily take the first value for each property. For example, it could have returned List(bluePrius, redLeon) instead.
Of course, IttayD's solution is still faster since it does only one traversal.
My solution also has the disadvantage that, if the collection has Cars that are actually the same, both will be in the output list. This could be fixed by removing filter and returning uniqueValues directly, with type From[T]. However, it seems like CanBuildFrom[Map[P, From[T]], T, From[T]] does not exist... suggestions are welcome!
With a collection and a function from a record to a key this yields a list of records distinct by key. It's not clear whether groupBy will preserve the order in the original collection. It may even depend on the type of collection. I'm guessing either head or last will consistently yield the earliest element.
collection.groupBy(keyFunction).values.map(_.head)
When will Scala get a nubBy? It's been in Haskell for decades.
If you want to remove duplicates and preserve the order of the list you can try this two liner:
val tmpUniqueList = scala.collection.mutable.Set[String]()
val myUniqueObjects = for(o <- myObjects if tmpUniqueList.add(o.property)) yield o
this is entirely a rip of #IttayD 's answer, but unfortunately I don't have enough reputation to comment.
Rather than creating an implicit function to convert your iteratble, you can simply create an implicit class:
import scala.collection.IterableLike
import scala.collection.generic.CanBuildFrom
implicit class RichCollection[A, Repr](xs: IterableLike[A, Repr]){
def distinctBy[B, That](f: A => B)(implicit cbf: CanBuildFrom[Repr, A, That]) = {
val builder = cbf(xs.repr)
val i = xs.iterator
var set = Set[B]()
while (i.hasNext) {
val o = i.next
val b = f(o)
if (!set(b)) {
set += b
builder += o
}
}
builder.result
}
}