R - Применить семейство (sapply vs. vapply) [дублировать]

Если вы хотите передавать данные с одного контроллера на другой, попробуйте этот код

FirstViewController.h

@property (nonatomic, retain) NSString *str;

SecondViewController.h

@property (nonatomic, retain) NSString *str1;

FirstViewController.m

- (void)viewDidLoad
   {
     // message for the second SecondViewController
     self.str = @"text message";

     [super viewDidLoad];
   }

-(IBAction)ButtonClicked
 {
   SecondViewController *secondViewController = [[SecondViewController alloc] initWithNibName:@"SecondViewController" bundle:nil];
   secondViewController.str1 = str;
  [self.navigationController pushViewController:secondViewController animated:YES];
 }
70
задан MichaelChirico 31 August 2015 в 00:12
поделиться

3 ответа

Как уже отмечалось, vapply выполняет две функции:

  • Улучшение медленной скорости
  • Улучшает согласованность, обеспечивая ограниченную проверку типа возврата.

Второй момент - большее преимущество, поскольку он помогает ловить ошибки до их возникновения и приводит к более надежному коду. Эта проверка возвращаемого значения может быть сделана отдельно с помощью sapply, а затем stopifnot, чтобы убедиться, что возвращаемые значения соответствуют ожидаемым, но vapply немного проще (если они более ограничены, так как пользовательский код проверки ошибок может проверять значения в пределах границ и т. д.).

Вот пример vapply, гарантирующий, что ваш результат будет таким, как ожидалось. Это сравнивает то, над чем я только что работал, в то время как PDF-скребок, где findD использовал для соответствия шаблону в необработанных текстовых данных (например, у меня был бы список, который был split сущностью , и регулярное выражение для соответствия адресам внутри каждого объекта. Иногда PDF-код был преобразован вне порядка, и для объекта было бы два адреса, что вызвало нехорошее состояние.)

> input1 <- list( letters[1:5], letters[3:12], letters[c(5,2,4,7,1)] )
> input2 <- list( letters[1:5], letters[3:12], letters[c(2,5,4,7,15,4)] )
> findD <- function(x) x[x=="d"]
> sapply(input1, findD )
[1] "d" "d" "d"
> sapply(input2, findD )
[[1]]
[1] "d"

[[2]]
[1] "d"

[[3]]
[1] "d" "d"

> vapply(input1, findD, "" )
[1] "d" "d" "d"
> vapply(input2, findD, "" )
Error in vapply(input2, findD, "") : values must be length 1,
 but FUN(X[[3]]) result is length 2

Как я говорю мои ученики, часть становления программистом, меняют ваше мышление с «ошибок раздражают» на «ошибки - мой друг».

Входы нулевой длины Одна связанная точка состоит в том, что если входная длина равна нулю, sapply всегда будет возвращать пустой список, независимо от типа ввода. Сравнение:

sapply(1:5, identity)
## [1] 1 2 3 4 5
sapply(integer(), identity)
## list()    
vapply(1:5, identity)
## [1] 1 2 3 4 5
vapply(integer(), identity)
## integer(0)

С помощью vapply вы гарантированно получите определенный тип вывода, поэтому вам не нужно писать дополнительные проверки на входы с нулевой длиной.

Тесты

vapply могут быть немного быстрее, потому что он уже знает, в каком формате он должен ожидать результатов.

input1.long <- rep(input1,10000)

library(microbenchmark)
m <- microbenchmark(
  sapply(input1.long, findD ),
  vapply(input1.long, findD, "" )
)
library(ggplot2)
library(taRifx) # autoplot.microbenchmark is moving to the microbenchmark package in the next release so this should be unnecessary soon
autoplot(m)

autoplot [/g1]

59
ответ дан Richie Cotton 1 September 2018 в 00:27
поделиться

Если вы всегда хотите, чтобы ваш результат был чем-то конкретным ... например. логический вектор. vapply делает это, но sapply не обязательно это делает.

a<-vapply(NULL, is.factor, FUN.VALUE=logical(1))
b<-sapply(NULL, is.factor)

is.logical(a)
is.logical(b)
12
ответ дан jpd527 1 September 2018 в 00:27
поделиться

Дополнительные нажатия клавиш, связанные с vapply, могут сэкономить время на отладку запутанных результатов позже. Если функция, которую вы вызываете, может возвращать разные типы данных, обязательно следует использовать vapply.

Одним из примеров, который приходит на ум, будет sqlQuery в пакете RODBC. Если есть ошибка при выполнении запроса, эта функция возвращает вектор character с сообщением. Например, скажем, вы пытаетесь выполнить итерацию по вектору имен таблиц tnames и выберите максимальное значение из числового столбца NumCol в каждой таблице с помощью:

sapply(tnames, 
   function(tname) sqlQuery(cnxn, paste("SELECT MAX(NumCol) FROM", tname))[[1]])

Если все имена таблиц действительны, это приведет к созданию вектора numeric. Но если одно из имен таблиц происходит в базе данных и запрос не выполняется, результаты будут принудительно введены в режим character. Однако использование vapply с FUN.VALUE=numeric(1) остановит здесь ошибку и не позволит ей появиться где-то по линии --- или, что еще хуже, совсем нет.

13
ответ дан Matthew Plourde 1 September 2018 в 00:27
поделиться
Другие вопросы по тегам:

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