我怎么走
x <- list(p1 = list(type='A',score=list(c1=10,c2=8,c3=data.frame(a=1, b=3, c=5))),
p2 = list(type='B',score=list(c1=9,c2=9,c3=data.frame(a=2, b=2))),
p3 = list(type='B',score=list(c1=9,c2=7,c3=data.frame(a=2, b=2))))
到没有作为数据帧的“ c3”元素的列表?
最好以一种tidyverse
友好的方式,或者我可以在管道中间放置的东西。
我已经尝试过list.remove,嵌套的lapply,rapply,Filter,但似乎无法使它们正常工作...而且我不想取消列出嵌套的列表结构。
(编辑:对不起,我在原始问题中的示例数据中有错字(请参见下文),但是如果您的解决方案在两种情况下均有效,那就太好了!)
x <- list(p1 = list(type='A',score=list(c1=10,c2=8,c3=data.frame(a=1, b=3, c=5))),
p2 = list(type='B',score=list(c1=9,c2=9,c3=data.frame(a=2, b=2)),
p3 = list(type='B',score=list(c1=9,c2=7,c3=data.frame(a=2, b=2)))))
答案 0 :(得分:2)
这是使用modify_depth
的正确方案,它是modify
链访问深层嵌套列表的快捷方式。 modify
在这个问题上比map
有一个优势,因为它可以保留输入的类型,而不是将所有内容强制转换为列表,如果您具有列表结构的矢量元素,这可能是相关的。
使用给定的输入(内部包含p3
元素,而不是与p2
处于同一级别),第二级和第三级的数据帧元素将按以下方式discard
进行分类。为了搜索嵌套列表的所有级别,我们可以设置一个while
循环来遍历这些级别,并在处理过程中丢弃数据帧。我们需要.ragged = TRUE
来处理列表深度的错误。此版本从下至上搜索,但您也可以将其更改为从上至下搜索。
library(tidyverse)
x <- list(
p1 = list(type = "A", score = list(c1 = 10, c2 = 8, c3 = data.frame(a = 1, b = 3, c = 5))),
p2 = list(
type = "B", score = list(c1 = 9, c2 = 9, c3 = data.frame(a = 2, b = 2)),
p3 = list(type = "B", score = list(c1 = 9, c2 = 7, c3 = data.frame(a = 2, b = 2)))
)
)
remove_dataframes <- function(input_list) {
current_list <- input_list
current_depth <- vec_depth(current_list)
# current_depth <- max_depth
while (current_depth > 1) {
current_list <- modify_depth(
.x = current_list,
.depth = current_depth,
.f = ~ discard(., is.data.frame),
.ragged = TRUE
)
current_depth <- current_depth - 1
}
return(current_list)
}
x %>%
remove_dataframes %>%
glimpse
#> List of 2
#> $ p1:List of 2
#> ..$ type : chr "A"
#> ..$ score:List of 2
#> .. ..$ c1: num 10
#> .. ..$ c2: num 8
#> $ p2:List of 3
#> ..$ type : chr "B"
#> ..$ score:List of 2
#> .. ..$ c1: num 9
#> .. ..$ c2: num 9
#> ..$ p3 :List of 2
#> .. ..$ type : chr "B"
#> .. ..$ score:List of 2
由reprex package(v0.2.1)于2019-02-20创建
答案 1 :(得分:2)
您可以编写自己的函数来做到这一点:
class Person
{
public int Id { get; set; }
public string Name { get; set; }
}
public override void Configure(Container container)
{
SetConfig(new HostConfig {
DefaultRedirectPath = "/metadata",
DebugMode = AppSettings.Get(nameof(HostConfig.DebugMode), false)
});
container.Register<IDbConnectionFactory>(c => new OrmLiteConnectionFactory(
"Server=localhost;Database=test;UID=root;Password=test;SslMode=none",
MySqlDialect.Provider));
using (var db = container.Resolve<IDbConnectionFactory>().OpenDbConnection())
{
db.DropAndCreateTable<Person>();
db.Insert(new Person {Id = 1, Name = "Name"});
var s = db.Select<Person>().Dump();
s.PrintDump();
}
var model = ModelDefinition<Person>.Definition;
model.Name.Print();
}
这也很受欢迎,因为它可以丢弃您需要的所有东西。例如,尝试check = function(x,name){
m = names(x)%in% name
x = if(any(m)) x[!m] else x
if(is.list(x)) sapply(x,check,name)
else x
}
dput(check(x,'c3'))
list(p1 = list(type = "A", score = list(c1 = 10, c2 = 8)), p2 = list(
type = "B", score = list(c1 = 9, c2 = 9), p3 = list(type = "B",
score = list(c1 = 9, c2 = 7))))
答案 2 :(得分:2)
这是在 rrapply()
包中使用 rrapply
的另一种替代方法,适用于任意级别的嵌套:
library(rrapply)
x1 <- rrapply(x, condition = function(x, .xparents) !any(.xparents == "c3"), how = "prune")
str(x1)
#> List of 3
#> $ p1:List of 2
#> ..$ type : chr "A"
#> ..$ score:List of 2
#> .. ..$ c1: num 10
#> .. ..$ c2: num 8
#> $ p2:List of 2
#> ..$ type : chr "B"
#> ..$ score:List of 2
#> .. ..$ c1: num 9
#> .. ..$ c2: num 9
#> $ p3:List of 2
#> ..$ type : chr "B"
#> ..$ score:List of 2
#> .. ..$ c1: num 9
#> .. ..$ c2: num 7