Как я должен добавить несколько идентичных элементов к отделению с jQuery

По сути, вы должны создать выражение Column, которое приведёт ваш ввод к типу с очищенными именами полей. Для этого вы можете использовать функцию org.apache.spark.sql.functions.struct, которая позволяет комбинировать другие Column для создания столбца структурного типа. Нечто подобное должно работать:

  import org.apache.spark.sql.{functions => f}

  def sanitizeName(s: String): String = s.replace(" ", "_")

  def sanitizeFieldNames(st: StructType, context: String => Column): Column = f.struct(
    st.fields.map { sf =>
      val sanitizedName = sanitizeName(sf.name)
      val sanitizedField = sf.dataType match {
        case struct: StructType =>
          val subcontext = context(sf.name)
          sanitizeFieldNames(struct, subcontext(_))
        case _ => context(sf.name)
      }
      sanitizedField.as(sanitizedName)
    }: _*
  )

Вы используете это так:

val df: DataFrame = ...

val appFieldType = df.schema("app").asInstanceOf[StructType]  // or otherwise obtain the field type
df.withColumn(
  "app",
  sanitizeFieldNames(appFieldType, df("app")(_))
)

Для вашего типа эта рекурсивная функция будет возвращать столбец типа

f.struct(
  df("app")("environment").as("environment"),
  df("app")("name").as("name"),
  f.struct(
    df("app")("type")("word tier").as("word_tier"),
    df("app")("type")("level").as("level")
  ).as("type")
)
[1120 ], который затем присваивается полю «app», заменяя то, что там присутствует.

Однако у этого решения есть ограничение. Он не поддерживает вложенные массивы или карты: если у вас есть схема со структурами внутри массивов или карт, этот метод не будет преобразовывать какие-либо структуры внутри массивов и карт. Тем не менее, в Spark 2.4 они добавили функции, которые выполняют операции с коллекциями, поэтому возможно, что в Spark 2.4 эта функция может быть обобщена для поддержки вложенных массивов и карт.

Наконец, можно делать то, что вы хотите с mapPartitions. Во-первых, вы пишете рекурсивный метод, который очищает только StructType вашего поля:

def sanitizeType(dt: DataType): DataType = dt match {
  case st: StructType => ...  // rename fields and invoke recursively
  case at: ArrayType => ...  // invoke recursively
  case mt: MapType => ...  // invoke recursively
  case _ => dt  // simple types do not have anything to sanitize
}

Во-вторых, вы применяете очищенную схему к вашему фрейму данных. Есть два основных способа сделать это: безопасный mapPartitions и один, который использует внутренний Spark API.

С mapPartitions это просто:

df.mapPartitions(identity)(RowEncoder(sanitizeType(df.schema)))

Здесь мы применяем операцию mapPartitions и явно указываем выходной кодер. Помните, что схемы в Spark не свойственны данным: они всегда связаны с конкретным кадром данных. Все данные внутри фрейма данных представлены в виде строк без меток на отдельных полях, только позиции. Пока ваша схема имеет одинаковые типы на тех же позициях (но с потенциально разными именами), она должна работать так, как вы ожидаете.

mapPartitions действительно приводит к нескольким дополнительным узлам в логическом плане. Чтобы избежать этого, можно создать экземпляр Dataset[Row] непосредственно с помощью конкретного кодировщика:

new Dataset[Row](df.sparkSession, df.queryExecution.logical, RowEncoder(sanitizeType(df.schema)))

Это позволит избежать ненужного mapPartitions (что, как правило, приводит к десериализации-map-serialize шаги в плане выполнения запроса), но это может быть небезопасно; Я лично не проверял это сейчас, но это могло сработать для вас.

12
задан JasonMArcher 30 July 2015 в 18:15
поделиться

4 ответа

Если Вы захотите, чтобы IE был быстр - или обычно рассматривал скорость, то Вы захотите создать фрагмент DOM сначала прежде, чем вставить его.

John Resig объясняет технику и включает сравнительный тест производительности:

http://ejohn.org/blog/dom-documentfragments/

var i = 10, 
    fragment = document.createDocumentFragment(), 
    div = document.createElement('div');

while (i--) {
    fragment.appendChild(div.cloneNode(true));
}

$('#container').append(fragment);

Я понимаю, что это не делает большое использование jQuery в создании фрагмента, но я запустил несколько тестов, и я, может казаться, не делаю $ (фрагмент) .append () - но я читал, выпуск jQuery 1.3 John's, как предполагается, включает изменения на основе исследования, связанного выше.

19
ответ дан 2 December 2019 в 04:34
поделиться

Самый быстрый способ сделать это должно создать содержание сначала со строками. Это НАМНОГО быстрее для работы со строками для создания фрагмента документа прежде, чем работать с DOM или jQuery вообще. К сожалению, IE делает действительно плохое задание конкатенации строк, таким образом, лучший способ сделать это состоит в том, чтобы использовать массив.

var cont = []; //Initialize an array to build the content
for (var i = 0;i<10;i++) cont.push('<div>bunch of text</div>');
$('#container').html(cont.join(''));

Я использую эту технику тонна в моем коде. Можно создать очень большие фрагменты HTML с помощью этого метода, и это очень эффективно во всех браузерах.

7
ответ дан 2 December 2019 в 04:34
поделиться

Можно перенести собственный массив JavaScript в jQuery и использовать карту () для преобразования ее в jQuery (список узлов DOM). Это официально поддерживается.

$(['plop', 'onk', 'gloubi'])
.map(function(i, text)
{
    return $('<div/>').text(text).get(0);
})
.appendTo('#container');

Это создаст

<div id="container">
<div>plop</div>
<div>onk</div>
<div>gloubi</div>
</div>

Я часто использую эту технику, чтобы не повторять меня (DRY).

7
ответ дан 2 December 2019 в 04:34
поделиться

Можно использовать регулярный цикл с JQuery, добавляют функцию.

for(i=0;i<10; i++){
    $('#container').append("<div></div>");
}
0
ответ дан 2 December 2019 в 04:34
поделиться
Другие вопросы по тегам:

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