Определите scala udf, которые принимают любые параметры * в искровом [дубликат]

Да, вам нужно посмотреть на AlarmManager , чтобы настроить повторный «Тревога». Это лучше для аккумулятора на устройстве, так как в отличие от обслуживания он не работает постоянно в фоновом режиме. Тревога запускает приемник вещания , который будет выполнять ваш пользовательский код.

В качестве окончательной заметки - есть значения перечислимого времени для синхронизации сигнала тревоги, включая ежедневные, половинные сутки и многие другие хотя вы можете просто установить фактическое значение.

Хороший пример можно найти в следующем сообщении SO:

Пример диспетчера аварийных сигналов

Обновить

Новые функции были добавлены в Android. Если вы читаете это, я бы посоветовал вам теперь взглянуть на GcmNetworkManager . Это оптимизирует время работы от батареи и работает до леденца. Для Lollipop вы можете использовать JobScheduler . Я бы посоветовал использовать эти классы над AlarmManager.

13
задан mrsrinivas 28 February 2017 в 18:48
поделиться

1 ответ

UDF не поддерживают varargs *, но вы можете передать произвольное количество столбцов, завернутых с помощью функции array:

import org.apache.spark.sql.functions.{udf, array, lit}

val myConcatFunc = (xs: Seq[Any], sep: String) => 
  xs.filter(_ != null).mkString(sep)

val myConcat = udf(myConcatFunc)

Пример использования:

val  df = sc.parallelize(Seq(
  (null, "a", "b", "c"), ("d", null, null, "e")
)).toDF("x1", "x2", "x3", "x4")

val cols = array($"x1", $"x2", $"x3", $"x4")
val sep = lit("-")

df.select(myConcat(cols, sep).alias("concatenated")).show

// +------------+
// |concatenated|
// +------------+
// |       a-b-c|
// |         d-e|
// +------------+

С сырым SQL:

df.registerTempTable("df")
sqlContext.udf.register("myConcat", myConcatFunc)

sqlContext.sql(
    "SELECT myConcat(array(x1, x2, x4), '.') AS concatenated FROM df"
).show

// +------------+
// |concatenated|
// +------------+
// |         a.c|
// |         d.e|
// +------------+

Немного более сложный подход не использует UDF вообще и составляет выражения SQL с примерно чем-то примерно следующим образом:

import org.apache.spark.sql.functions._
import org.apache.spark.sql.Column

def myConcatExpr(sep: String, cols: Column*) = regexp_replace(concat(
  cols.foldLeft(lit(""))(
    (acc, c) => when(c.isNotNull, concat(acc, c, lit(sep))).otherwise(acc)
  )
), s"($sep)?$$", "") 

df.select(
  myConcatExpr("-", $"x1", $"x2", $"x3", $"x4").alias("concatenated")
).show
// +------------+
// |concatenated|
// +------------+
// |       a-b-c|
// |         d-e|
// +------------+

, но я сомневаюсь стоит усилий, если вы не работаете с PySpark.


* Если вы передадите функцию с использованием varargs, она будет удалена из всего синтаксического сахара, и в результате UDF ожидает ArrayType. Например:

def f(s: String*) = s.mkString
udf(f _)

будет иметь тип:

UserDefinedFunction(<function1>,StringType,List(ArrayType(StringType,true)))
31
ответ дан zero323 16 August 2018 в 01:40
поделиться
  • 1
    Привет, Есть ли способ получить имя столбца при конкатенации ... – Kalpesh 23 August 2016 в 12:27
  • 2
    Нет, если вы не передадите имена столбцов явно как литералы. – zero323 23 August 2016 в 13:31
  • 3
    Привет, можете ли вы поделиться синтаксисом для того же – Kalpesh 23 August 2016 в 14:23
  • 4
    @Kalpesh array(df.columns.map(c => struct(lit(c), col(c)): _*) - & gt; udf(xs: Seq[Row] => ???). – zero323 23 August 2016 в 14:32
  • 5
    Обратите внимание на запись массива, а не на массив при вызове функции – Ameba Spugnosa 2 November 2016 в 10:16
Другие вопросы по тегам:

Похожие вопросы: