2016-08-24 2 views
2

Я ищу для создания функции в R, которая загружает значения по умолчанию для данной функции. Для этого я использую аргумент args для функции и хочу разбить ее на аргументы функции по умолчанию и загрузить их в глобальную среду. Это требует немного регулярных выражений и натолкнулось на это, с которыми мне трудно справляться.Регулярное выражение Выберите запятую, но не внутри между скобками

Вот пример функции:

myFunc <- function(a = 1, b = "hello world", c = c("Hello", "World")) {} 

Я получил его до этой точки, используя свои собственные функции:

x <- "a = 1, b = \"hello world\", c = c(\"Hello\", \"World\")" 

Однако, когда я борюсь на разделив аргументы функции вверх. Я хотел разбить запятую, но если у вас есть аргумент функции, который имеет запятую в пределах значения по умолчанию (например, аргумент), это вызывает проблемы. Я думаю, что если есть способ вызвать регулярное выражение, соответствующее запятой, но не запятую между двумя круглыми скобками, то я мог бы использовать strsplit с этим выражением, чтобы получить то, что я хочу.

Моя попытка соответствовать случай запятой между двумя скобками выглядит следующим образом:

\\(.*,.*\\) 

Теперь, я посмотрел в том, чтобы делать то, что я описал выше, и кажется отрицательным прогностическим может быть тем, что мне нужно, поэтому я попытался сделать что-то подобное.

splitx <- strsplit(x, "(?!\\(.*,.*\\)(,)") 

Но R говорит мне, что это незаконное регулярное выражение. Если я установил в аргументе perl = TRUE, он просто вернет ту же строку. Любая помощь здесь была бы очень признательна, и я надеюсь, что я был ясен!

+1

С помощью регулярного выражения PCRE легко справиться с чем-то другим - ['strsplit (x," \\ ([^)] + \\) (* SKIP) (* F) |, ", perl = TRUE)'] (http://ideone.com/Cw6U5n). Однако убедитесь, что вы не находитесь в тупике с регулярными выражениями здесь. –

+3

Ваш вопрос имеет гораздо более широкий охват, чем проблема, с которой вы сталкиваетесь. Был бы я кратковременным, если бы я предположил, что 'match.call()' может быстрее привести вас к цели? –

+1

Некоторые поиски найдут более подробную информацию, но вы можете начать здесь: http://stackoverflow.com/questions/14397364/match-call-with-default-arguments –

ответ

7

Я собираюсь попытаться ответить на ваш основной вопрос.

Функция formals() возвращает парный список формальных аргументов функции. Вы можете использовать результат formals() путем тестирования на is.symbol() и is.null(). Все, что не является символом и не равно null, содержит значение по умолчанию.

Например:

get_default_args <- function(fun){ 
    x <- formals(fun) 
    w <- sapply(x, function(x)!is.symbol(x) && !is.null(x)) 
    x[w] 
} 

ПРИМЕРЬТЕ lm():

get_default_args(lm) 
$method 
[1] "qr" 

$model 
[1] TRUE 

$x 
[1] FALSE 

$y 
[1] FALSE 

$qr 
[1] TRUE 

$singular.ok 
[1] TRUE 

Попробуйте это на вашей функции:

myFunc <- function(a = 1, b = "hello world", c = c("Hello", "World")) {} 
get_default_args(myFunc) 
$a 
[1] 1 

$b 
[1] "hello world" 

$c 
c("Hello", "World") 

Обратите внимание, что комментарии наводит на мысль, используя match.call(). Это может работать или не работать для вас, но match.call() оценивает аргумент в среде функции после вызова, тогда как formals() оценивает сам язык. Поэтому вам не нужно вообще вызывать функцию при использовании formals().

+0

Довольно классный материал, и аргумент 'formals()' очень полезен. Спасибо за это! – giraffehere

+0

Моя поддержка 'match.call()', возможно, неправильно использует прецедент здесь. Этот ответ ('formals()') корректно обрабатывает то, что я теперь думаю, что OP пытается достичь, и хотя он получает от меня верхнюю часть, официальный вопрос формально относится к регулярному выражению, поэтому я ответил на это ниже. –

+0

Да, лад. Андри просто перешел к вопросу к моей более всеобъемлющей цели. – giraffehere

1

Хотя я не думаю, что это правильный подход (использование match.call() для извлечения аргументов, как они были приняты), совпадающий регулярное выражение

x <- "a = 1, b = \"hello world\", c = c(\"Hello\", \"World\")" 
strsplit(x, ",(?![^()]*\\))", perl=TRUE) 

#> [[1]] 
#> [1] "a = 1"      " b = \"hello world\""   " c = c(\"Hello\", \"World\")" 
+0

Я считаю, что проблема с 'match.call' в моем случае что он должен использоваться внутри функции, тогда как я хочу использовать это вне функции. – giraffehere

+1

Да, я неправильно понял вашу цель. 'formals()' - это тот подход, который вы, вероятно, хотите, но ваш вопрос, как указано, все еще касается регулярного выражения, отсюда и этот ответ. –

Смежные вопросы