Я никогда не использовал Filter
до вашего вопроса, так что это было хорошее упражнение для первой вещи утром:)
Есть, по крайней мере, пара вещей, которые сбивают вас с толку(Я думаю).
Давайте начнем с вашей первой простой анонимной функции, но давайте сделаем ее отдельной, чтобы ее было легче читать:
f <- function(i){
z[[i]] > 1
}
Вам должно показаться, что эта функция принимает один аргумент, i
, но в функции он вызывает z
.Это не очень хорошее «функциональное» программирование:)
Итак, начните с изменения этой функции на:
f <- function(i){
i > 1
}
И вы увидите, что Filter
фактически будет работать со списком списков:
z <- list(z1=list(a=1,b=2,c=3), z2=list(a=1,b=1,c=1))
Filter( f, z)
но возвращается:
> Filter( f, z)
$z2
$z2$a
[1] 1
$z2$b
[1] 1
$z2$c
[1] 1
$<NA>
NULL
, что не совсем то, что вы хотите.Честно говоря, я не могу понять, почему он возвращает такой результат, может быть, кто-то может мне это объяснить.
@ DWin лаял правильное дерево, когда он сказал, что должно быть рекурсивное решение.Я взломал первый удар рекурсивной функции, но вам нужно улучшить его:
fancyFilter <- function(f, x){
if ( is.list( x[[1]] ) ) #only testing the first element... bad practice
lapply( x, fancyFilter, f=f ) #recursion FTW!!
else
return( lapply(x, Filter, f=f ) )
}
fancyFilter
смотрит на первый элемент x
, переданный ему, и если этот элементэто список, он рекурсивно вызывает fancyFilter
для каждого элемента списка.Но что, если элемент № 2 не является списком?Это то, что вы должны проверить и выяснить, имеет ли это значение для вас.Но результат fancyFilter
выглядит так, как вы хотите:
> fancyFilter(f, z)
$z1
$z1$a
numeric(0)
$z1$b
[1] 2
$z1$c
[1] 3
$z2
$z2$a
numeric(0)
$z2$b
numeric(0)
$z2$c
numeric(0)
Возможно, вы захотите добавить некоторую логику, чтобы очистить вывод, чтобы результаты FALSE
не приставали к numeric(0)
.И, очевидно, я сделал пример, используя только вашу простую функцию, а не более сложную функцию, которую вы использовали во втором примере.