Char или String → Unicode значение в Scala?
Итак, я работаю над несколькими упражнениями в "Scala для нетерпимого", и один из них:
Напишите цикл for
для вычисления произведения кодов Юникода всех букв в строке. Например, произведение символов в "Привет" равно 9415087488 L.
Следующая проблема заключается в том, чтобы сделать то же самое, но без цикла for
- подсказывает, что мы должны проверять StringOps
в Scaladoc.
Я проверил раздел RichChar
и StringOps
в Scaladoc, и, возможно, я неправильно читаю или смотрю не в то место, но я не могу найти ничего, что позволило бы мне соответствовать их результатам. Я до сих пор пробовал:
scala> x.foldLeft(1)(_ * _.toInt)
res0: Int = 825152896
scala> x.foldLeft(1)(_ * _.getNumericValue)
res5: Int = 2518992
scala> x.foldLeft(1)(_ * _.intValue())
res6: Int = 825152896
scala> var x = 1
x: Int = 1
scala> for (c <- "Hello") x *= c.toInt
scala> x
res12: Int = 825152896
Что не соответствует их выходу.
Как это сделать, как в for
, так и не for
?
Спасибо!
Ответы
Ответ 1
Когда вы выполняете x.foldLeft(1)(_ * _.toInt)
, тип результата будет выводить на Int
, но 9415087488 слишком велик для Int
для его сохранения.
Итак, вам нужно сказать Scala, используя Long
, чтобы сохранить его.
scala> val x = "Hello"
x: java.lang.String = Hello
scala> x.foldLeft(1L)(_ * _.toInt)
res1: Long = 9415087488
scala> var x: Long = 1
x: Long = 1
scala> for (c <- "Hello") x *= c.toInt
scala> x
res7: Long = 9415087488
Ответ 2
Если вы конвертируете каждый RichChar из String.toLong, он также работает. Например, это:
str.map (_.toLong).product
- работать отлично и без foldLeft или циклов
Это циклический вариант:
def product(str: String): Long = {
var prod: Long = 1
for (ch <- str) prod *= ch
prod
}
Ответ 3
В StringOps существует специальный метод "продукта", который умножает элементы коллекции. Но он использует тип Char, потому что строка состоит из элементов Char. И у нас переполнение при попытке вычислить "Hello".product. Поэтому я преобразовал строку в значения Vector of Long Unicode с помощью "Hello".map(_. ToLong) и вычислил произведение своих элементов по этому коду:
scala> "Hello".map(_.toLong).product
res79: Long = 9415087488
Ответ 4
Здесь другой способ:
scala> (for (c <- "Hello") yield c.toLong).product
res36: Long = 9415087488
Ответ 5
Самый простой способ, который я нашел, это:
"Hello".foldLeft(1L)((x:Long, y:Char) => x*y)
Метод принимает два параметра: Long и функция делегата, которая принимает длину и a Char, и возвращает Long. Вы можете передать анонимную функцию прямо так, или вы можете определить функцию в другом месте и передать ее, например:
def multiply(x:Long, y:Char) = {
x*y
}
"Hello".foldLeft(1L)(multiply)
Ответ 6
Я думаю, что преобразование в промежуточную карту неэффективно, потому что в этом случае коллекция повторяется дважды: один раз для создания карты длин и второй раз для умножения всех элементов. Необязательный временный сбор Long также не нужен. Я отдаю свой голос
"Hello".foldLeft(1L)(_ * _)
Ответ 7
Другой вариант:
"Hello".aggregate(1L)({(prod,ch) => prod * ch.toLong}, {(p1,p2)=>p1*p2})