Условие в функции карты

Есть ли в Scala что-нибудь вроде,

condition ? first_expression : second_expression;

что я могу использовать в функции карты в scala? Я хочу написать что-то вроде этого:

val statuses = tweets.map(status => status.isTruncate? //do nothing | status.getText())

Если встроенная функция невозможна, как я могу написать условие в map?


person Lisa    schedule 03.04.2015    source источник


Ответы (2)


Оператор ?, иногда называемый тернарным оператором, не нужен в Scala, поскольку он входит в состав регулярного выражения if-else:

val x = if (condition) 1 else 2

Чтобы использовать это в map, вы можете использовать flatMap, а затем вернуть Option по обе стороны от if-else. Поскольку Option неявно преобразуется в Iterable, в результате список сглаживается, а Nones фильтруются:

val statuses = tweets.flatMap(status => if (status.isTruncate) None else Some(status.getText))

Это эквивалентно использованию map, а затем flatten:

val statuses = tweets.map(status => if (status.isTruncate) None else Some(status.getText)).flatten

Более идиоматично, вы можете использовать collect, что позволяет вам filter и map за один шаг, используя частичную функцию:

val statuses = tweets.collect {
    case status if !status.isTruncate => status.getText
}

Вы также можете сделать это за 2 шага, используя filter и map:

val statuses = tweets.filterNot(_.isTruncate).map(_.getText)

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

val statuses = tweets.view.filterNot(_.isTruncate).map(_.getText)
person Ben Reich    schedule 03.04.2015
comment
Поскольку вопрос помечен как apache-spark, tweets, скорее всего, является RDD. В этом случае нет ни filterNot метода, ни views. Однако RDD по своей природе ленивы, поэтому в views тоже нет необходимости. - person Daniel Darabos; 04.04.2015
comment
Мы также можем использовать withFilter для фильтрации только в последующих операциях, таких как map. scala-lang.org/api/current/scala/collection/ - person juanmirocks; 09.04.2020

вы можете отфильтровать, а затем сопоставить,

  val statuses = tweets.filter(_.isTruncate).map(status=> status.getText())
person S.Karthik    schedule 03.04.2015
comment
Это не предпочтительный способ решения проблемы. Это приводит к тому, что отфильтрованные элементы проходят два раза; все элементы для фильтрации проходят, а затем успешно отфильтрованные элементы во второй раз. Учитывая большой список и значительный процент, который сохраняется с фильтром, ваше решение также довольно неэффективно. Кстати, последняя строка ответа Бена использует представление, которое может сделать ваше решение эффективным. - person chaotic3quilibrium; 10.05.2016