Количество Count строк, которые могут быть преобразованы в Int в списке

Например, мой ввод:

scala> val myList = List("7842", "abf45", "abd", "56")
myList: List[String] = List(7842, abf45, abd, 56)

7842 и 56 можно преобразовать в Int; поэтому мой ожидаемый результат равен 2. Мы можем предположить, что отрицательных целых чисел не бывает, поэтому -67 невозможно.

Это то, что у меня есть до сих пор:

scala> myList.map(x => Try(x.toInt).getOrElse(-1)).count(_ > -1)
res15: Int = 2

Это должно работать правильно, но я чувствую, что мне не хватает более элегантного и читаемого решения, потому что все, что мне нужно сделать, - это количество успехов.

Ответ 1

Я бы предостерег от использования обработки исключений (например, Try) в потоке управления - он очень медленный.

Здесь решение, которое использует идиоматические операции коллекции Scala, работает хорошо и не будет считать отрицательные числа:

scala> val myList = List("7842", "abf45", "abd", "56")
myList: List[String] = List(7842, abf45, abd, 56)

scala> myList.count(_.forall(_.isDigit)) 
res8: Int = 2

EDIT: @immibis указал, что это не будет определять строки чисел, которые превышают Integer.MaxValue. Если это вызывает беспокойство, я бы рекомендовал один из следующих способов:

import scala.util.Try
myList.count(x => Try(x.toInt).filter(_ >= 0).isSuccess)

или, если вы хотите сохранить производительность моего первого ответа, продолжая обрабатывать этот край:

import scala.util.Try
myList.count(x => x.forall(_.isDigit) && Try(x.toInt).filter(_ >= 0).isSuccess)

Ответ 2

Это немного короче:

myList.count(x => Try(x.toInt).isSuccess)

Обратите внимание, что это решение будет обрабатывать любую строку, которая может быть преобразована в целое число через .toInt, включая отрицательные числа.

Ответ 3

Вы можете рассмотреть метод string.matches с регулярным выражением, чтобы соответствовать только положительным целям:

val myList = List("7842", "abf45", "abd", "-56")
// myList: List[String] = List(7842, abf45, abd, -56)

myList.count(_.matches("\\d+"))
// res18: Int = 1

Если отрицательные целые числа нужно подсчитать (и учитывать возможные знаки +/-):

myList.count(_.matches("[+-]?\\d+"))
// res17: Int = 2

Ответ 4

Начиная с Scala 2.13 и представляя String::toIntOption, мы можем подсчитывать элементы ("34"/"2s3"), для которых определено применение toIntOption (Some(34)/None) (true/false):

List("34", "abf45", "2s3", "56").count(_.toIntOption.isDefined) // 2