Распаковка списков аргументов для многоточия в R - PullRequest
36 голосов
/ 05 августа 2010

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

В Python это называется «распаковка списков аргументов», например,

>>> range(3, 6)             # normal call with separate arguments
[3, 4, 5]
>>> args = [3, 6]
>>> range(*args)            # call with arguments unpacked from a list
[3, 4, 5]

Например, в R у вас есть функция file.path(...), которая использует многоточие. Я хотел бы иметь такое поведение:

> args <- c('baz', 'foob') 
> file.path('/foo/bar/', args)
[1] 'foo/bar/baz/foob'

Вместо этого я получаю

[1] 'foo/bar/baz' 'foo/bar/foob'

, где элементы args не "распакованы" и оценены одновременно. Есть ли R эквивалентный Pythons *arg?

Ответы [ 3 ]

37 голосов
/ 05 августа 2010

Синтаксис не так красив, но это делает трюк:

do.call(file.path,as.list(c("/foo/bar",args)))

do.call принимает два аргумента: функцию и список аргументов для вызова этой функции.

20 голосов
/ 05 августа 2010

Вы можете извлечь информацию из многоточия, вызвав list(...) внутри функции. В этом случае информация в многоточии упаковывается как объект списка. Например:

> foo <- function(x,...){
+   print(list(...))
+ }
> foo(1:10,bar = 'bar','foobar')
$bar
[1] "bar"

[[2]]
[1] "foobar"

Вы можете добиться желаемого поведения с помощью векторизованных функций, таких как file.path, с помощью вызова do.call, который иногда проще использовать с оболочкой splat (в пакете plyr)

> args <- c('baz', 'foob')
> library(plyr)
> splat(file.path)(c('/foo/bar', args))
[1] "/foo/bar/baz/foob"
0 голосов
/ 08 октября 2018

Мне потребовалось некоторое время, чтобы найти его, но пакет purrr имеет эквивалент plyr::splat: он называется lift_dl.

«dl» в названии обозначает «список точек», поскольку является частью серии lift_xy функций, которые можно использовать для «поднятия» домена функции из одного вида ввода.к другому виду эти «виды» являются списками, векторами и «точками».

Поскольку lift_dl, вероятно, является наиболее полезным из них, для него предусмотрен простой псевдоним lift.

Чтобы использовать приведенный выше пример:

> library(purrr)
> args <- c('baz', 'foob')
> lift(file.path)(c('/foo/bar', args))
[1] "/foo/bar/baz/foob"
...