Does Scala have a native way to count all occurrences of a character in a string?
If so, how do I do it?
If not, do I need to use Java? If so, how do I do that?
Thanks!
"hello".count(_ == 'l') // returns 2
i don't use Scala or even java but google search for "Scala string" brought me to here
which contains :
def
count (p: (Char) ⇒ Boolean): Int
Counts the number of elements in the string which satisfy a predicate.
p
the predicate used to test elements.
returns
the number of elements satisfying the predicate p.
Definition Classes
TraversableOnce → GenTraversableOnce
Seems pretty straight forward but i dont use Scala so don't know the syntax of calling a member function. May be more overhead than needed this way because it looks like it can search for a sequence of characters. read on a different result page a string can be changed into a sequence of characters and you can probably easily loop through them and increase a counter.
You can also take a higher level approach to look into substring occurrences within another string, by using sliding:
def countSubstring(str: String, sub: String): Int =
str.sliding(sub.length).count(_ == sub)
Related
I am trying to write a function that
takes a List read from a file as input
outputs the most frequently used string as well an integer that shows the number of times that it was used.
example output:
("Cat",5)
function signature:
def mostFreq(info: List[List[String]]): (String, Int) =
First,I thought about creating a
Map variable and a counter variable
iterating over my list to fill the map
then iterate over the map
However, there must be a simpler way to do this scala but I'm not used to scala's library just yet.
I have seen this as one way to do it that uses only integers.
Finding the most frequent/common element in a collection?
But I was wondering how it could be done using string and integers.
The solution from the linked post has just about everything you need for this.
def mostFreq(info: List[List[String]]): (String, Int) =
info.flatten.groupBy(identity).mapValues(_.size).maxBy(_._2)
It doesn't handle ties terribly well, but you haven't stated how ties should be handled.
I'm creating a method to retrieve a list of users from a database by ID.
I'm trying to decide on the pros and cons of declaring the ids parameter as Option[Seq[String]] vs Seq[Option[String]]?
In what cases should I favour one over the other?
A list of users in neither well represented as an Option[Seq[String]] nor as a Seq[Option[String]]. I would expect something like a List[User] as a list of users. Or maybe a Vector or Seq
If your string represents your user, and the None case does nothing, you could consider filtering those out. You can do this with
val dbresult: Seq[Option[String]] = ???
val strings = dbresult collect { case Some(str) => str }
or
val strings = dbresult.flatten
but it's difficult to give good advice without knowing what the Option[String] or Option[Seq] represents
As usual this strongly depends on the use case.
A Seq[Option[String]] will be useful if the size of the sequence is relevant (eg., because you want to zip it with another sequence).
If this is not the case I would opt for flattening the sequence in order to just have a Seq[String]. This will likely be a better choice than Option[Seq[String]], as the sequence can also be of zero length.
In fact an Option can usually be treated as if it where an array that can have either length zero or one. Therefore wrapping an Iterable in an Option often only adds unnecessary complexity.
I'd like to remove only the few last elements of a List (or Seq), and avoid parsing all elements (and avoid applying the filter function to all of them).
Let's say, for example, I have a random strictly increasing list of values:
import scala.util.Random.nextInt
val r = (1 to 100).map(_ => nextInt(10)+1).scanLeft(0)(_+_)
And I want to remove the elements greater than, say, 300. I can do this like that:
r.filter(_<300)
but this method parse the whole list. So, is it possible to filter a list only on one end? Something like a filterRight method?
subquestions:
Also, would it be possible for list of values that are not strictly increasing? i.e. remove the elements from the end of a list until one element is, say, below 300.
if it is not possible for a List/Seq, what about IndexedSeq like Vector or Array
Solutions
I selected #elm solution because it answers the subquestion for general list, not only (strictly) increasing ones.
However, the solution of #dcastro looks to be more efficient as it doesn't do 2 reverse
First note SI-4247 on dropWhile but no dropRightWhile.
Though, a simple implementation that conveys the desired semantics,
def dropRightWhile[A](xs: Seq[A], p: A => Boolean) =
xs.reverse.dropWhile(p).reverse
or equivalently
implicit class OpsSeq[A](val xs: Seq[A]) extends AnyVal {
def dropRightWhile(p: A => Boolean) = xs.reverse.dropWhile(p).reverse
}
You're looking for something like dropRightWhile, which doesn't exist in the standard library (but has been requested before).
I think your best bet is:
r.takeWhile(_<300)
Since it's an increasing list of values, you can stop performing any checks when you first encounter an element greater than 300
A function of mine is to take from zero to five integer arguments and from zero to five string arguments. So I consider it to define as a function of 2 lists: f(numbers: List[Int], strings: List[String]). But I think it is good to constraint the lengths if it is possible, for an IDE and/or a compiler can enforce it. Is this possible?
I think you're really asking a lot of the type system for this one... This is a classic task for dependently typed programming, in which category Scala unfortunately does not belong.
You could look at Mark Harrah's type-level Naturals:
type _0 = Nat0
type _1 = Succ[_0]
type _2 = Succ[_1]
// ...
But if you go down this route, you'll have to build all your lists in such a way that the length-type is evident to the compiler. That means no recursion, no unbounded looping, etc. Also you'll have to come up with a way to encode "<" in the type system... since you can't do recursion I'm not sure how you'd do that. So, probably not worth it.
Maybe another way to approach the problem is to figure out where '0..5' comes from and constrain some other type based on that information?
As a last resort you could define special cases for the allowable sizes, separated so that you don't have 25 cases:
case class Small[+X](l: List[X])
def small(): Small[Nothing] = Small(List())
def small[A](a: A): Small[A] = Small(List(a))
def small[A](a1: A, a2: A): Small[A] = Small(List(a1,a2))
I want to find a key in a map that is similar to a specific text. should I use for loop or is there a more elegant way?
The direct translation of your question is map.keys.find(_.matches(pattern)) which given a map, gets they keys and finds the first key that matches the regexp pattern.
val map = Map("abc" -> 1, "aaa" -> 2, "cba" -> 3)
map.keys.find(_.matches("abc.*"))
// Some(abc)
map.keys.find(_.matches("zyx"))
// None
A loop may be counter productive if you don't want to scan all keys.
Suppose you have some regular expression which you wish to match on:
val RMatch = """\d+:(\w*)""".r
And a function, which takes the matched group for the regex, and the value in the map
def f(s: String, v: V): A
Then you can match on the regex and collect the value of the function:
map collectFirst { case (RMatch(_), v) => f(txt, v) }
If you just wanted the value...
map collectFirst { case (RMatch(txt), v) => v }
Note: the implementation of this method effects a traversal on the map, in case that is not what you were desiring
It depends on the pattern and the map's underlying implementation. If the map is a HashMap, then it can only give you an exact match against a key, so you can't do anything better than loop over its keys. If the map is a SortedMap and you know the beginning of the text you're looking for, then you can use the range method to obtain a part of the map based on the pattern, and loop over that range.
It really depends on what you mean by 'similar to' and 'text'. If you are using English words you could use the Soundex algorithm (http://en.wikipedia.org/wiki/Soundex) to give you a code for each word and use that as a hash key, collecting all the words with the same Soundex value together in a list. If you want to do full text matching then it's a lot more complicated and you need to use techniques such as Inverted Indexes (http://en.wikipedia.org/wiki/Inverted_index). In that case you'd be best looking at something pre-written such as Apache Lucene (http://lucene.apache.org/java/docs/) which gives you much more besides simple inverted indexes. Lucene is written in Java, so it is directly usable from Scala.