SingleOrDefault: Как изменить значения по умолчанию?

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

val tsDF = dataDF.select("TEST_PK", "h_timestamp")

Затем удалите столбец из dataDF, выполните свою операцию и снова присоедините h_timestamp обратно на новый фрейм данных.

val finalDF = postopDF.join(tsDF, "TEST_PK")

Обновление

Пример кода полезен, вы должны иметь возможность существенно разбить вашу строку и перестроить новую строку с нужными значениями примерно так: [ 1113]

dataDF.map(row => {
  val rowWithoutTimestamp = Row(
    row.getAs[Long]("TEST_PK"),
    row.getAs[String]("COL_1"),
    row.getAs[Long]("COL_2"),
    row.getAs[Double]("COL_3")
  )
  val timestamp = row.getAs[Long]("h_timestamp")
  val result = operation(rowWithoutTimestamp, timestamp)
  Row(result, timestamp)
})

Конечно, я не уверен, что возвращает ваш operation(), поэтому может потребоваться разобрать result на отдельные значения и составить новую строку с этими и отметкой времени.

Обновление 2

Хорошо, вот более общий метод. Он упаковывает «все столбцы, кроме» h_timestamp в структуру, и отображает поверх кортежа (struct, ts). Во всяком случае, на самом деле более элегантно, чем предыдущее решение.

val cols = df.drop("h_timestamp").columns.toSeq
dataDF
  .select(struct(cols.map(c => col(c)):_*).as("row_no_ts"), $"h_timestamp")
  .map(row => {
    val rowWithoutTimestamp = row.getAs[Row]("row_no_ts")
    val timestamp = row.getAs[Long]("h_timestamp")
    operation(rowWithoutTimestamp, timestamp)
  })

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

34
задан Benjamin 7 December 2013 в 21:07
поделиться

4 ответа

, вы можете сделать что-то вроде

myStrings.DefaultIfEmpty("myDefaultString").Single()

, проверить здесь

54
ответ дан 27 November 2019 в 16:21
поделиться

?? Оператор . Если левый аргумент равен нулю, оцените и верните второй аргумент.

myCollection.SingleOrDefault() ?? new[]{new Item(...)}

Это будет работать только со ссылочными типами (или обнуляемыми), но это сделает то, что вы ищете очень просто.

24
ответ дан 27 November 2019 в 16:21
поделиться

Вы можете бросить свой собственный.

public static T SingleOrDefault<T>(this IEnumerable<T> enumerable, T defaultValue) {
  if ( 1 != enumerable.Count() ) {
    return defaultValue;
  }
  return enumerable.Single();
}

Это может быть немного дороже, потому что Count () требует от вас обработки всей коллекции и может быть довольно дорогим для запуска. Было бы лучше либо вызвать Single, перехватить InvalidOperationException или выполнить метод IsSingle

public static bool IsSingle<T>(this IEnumerable<T> enumerable) {
  using ( var e = enumerable.GetEnumerator() ) {
    return e.MoveNext() && !e.MoveNext();
  }
}

public static T SingleOrDefault<T>(this IEnumerable<T> enumerable, T defaultValue) {
  if ( !enumerable.IsSingle() ) {
    if( enumerable.IsEmpty() ) { 
      return defaultValue;
    }
    throw new InvalidOperationException("More than one element");
  }
  return enumerable.Single();
}
5
ответ дан 27 November 2019 в 16:21
поделиться

Вы можете создать свои собственные методы расширения - SingleOrNew.

public static class IEnumerableExtensions
{
    public static T SingleOrNew<T>( this IEnumerable<T> enumeration, T newValue )
    {
        T elem = enumeration.SingleOrDefault();
        if (elem == null)
        {
            return newValue;
        }
        return elem;
    }

    public static T SingleOrNew<T>( this IEnumerable<T> enumeration, Func<T,bool> predicate, T newValue )
    {
        T elem = enumeration.SingleOrDefault( predicate );
        if (elem == null)
        {
            return newValue;
        }
        return elem;
    }
}
0
ответ дан 27 November 2019 в 16:21
поделиться
Другие вопросы по тегам:

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