Skip to content

Commit 11b8d04

Browse files
committed
feat(2606): adding list_search for nested data.table search
1 parent ce97148 commit 11b8d04

1 file changed

Lines changed: 82 additions & 12 deletions

File tree

R/tables.R

Lines changed: 82 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,28 +19,98 @@ type_size = function(DT) {
1919
}
2020

2121
tables = function(mb=type_size, order.col="NAME", width=80L,
22-
env=parent.frame(), silent=FALSE, index=FALSE)
22+
env=parent.frame(), silent=FALSE, index=FALSE,
23+
list_search=FALSE, list_len_threshold=100000L)
2324
{
2425
# Prints name, size and colnames of all data.tables in the calling environment by default
2526
mb_name = as.character(substitute(mb))
2627
if (isTRUE(mb)) { mb=type_size; mb_name="type_size" }
2728
names = ls(envir=env, all.names=TRUE) # include "hidden" objects (starting with .)
2829
obj = mget(names, envir=env) # doesn't copy; mget is ok with ... unlike get, #5197
2930
w = which(vapply_1b(obj, is.data.table))
30-
if (!length(w)) {
31+
32+
list_info = NULL
33+
if (list_search) {
34+
is_list = vapply_1b(obj, is.list)
35+
dt_mask = logical(length(obj))
36+
if (length(w)) dt_mask[w] = TRUE
37+
is_df = vapply_1b(obj, is.data.frame)
38+
list_candidates = which(is_list & !dt_mask & !is_df)
39+
40+
if (length(list_candidates)) {
41+
n_extra = 0L
42+
list_locations = vector("list", length(list_candidates))
43+
for (j in seq_along(list_candidates)) {
44+
obj_idx = list_candidates[j]
45+
L = obj[[obj_idx]]
46+
if (!is.list(L)) next
47+
lenL = length(L)
48+
if (is.finite(list_len_threshold) && lenL > list_len_threshold) next
49+
elem_is_dt = vapply_1b(L, is.data.table)
50+
idx = which(elem_is_dt)
51+
if (length(idx)) {
52+
list_locations[[j]] = idx
53+
n_extra = n_extra + length(idx)
54+
}
55+
}
56+
57+
if (n_extra) {
58+
list_info = data.table(NAME=character(n_extra), NROW=0L, NCOL=0L, MB=0.0, COLS=list(), KEY=list(), INDICES=list())
59+
extra_row = 0L
60+
for (j in seq_along(list_candidates)) {
61+
obj_idx = list_candidates[j]
62+
idx = list_locations[[j]]
63+
if (is.null(idx) || !length(idx)) next
64+
L = obj[[obj_idx]]
65+
obj_name = names[obj_idx]
66+
elem_names = names(L)
67+
for (k in idx) {
68+
extra_row = extra_row + 1L
69+
DT = L[[k]]
70+
if (!is.null(elem_names) && length(elem_names) >= k && nzchar(elem_names[k])) {
71+
nm = paste0(obj_name, "$", elem_names[k])
72+
} else {
73+
nm = paste0(obj_name, "[[", k, "]]")
74+
}
75+
set(list_info, extra_row, "NAME", nm)
76+
set(list_info, extra_row, "NROW", nrow(DT))
77+
set(list_info, extra_row, "NCOL", ncol(DT))
78+
if (is.function(mb)) set(list_info, extra_row, "MB", as.integer(mb(DT)/1048576L))
79+
if (!is.null(tt<-names(DT))) set(list_info, extra_row, "COLS", tt)
80+
if (!is.null(tt<-key(DT))) set(list_info, extra_row, "KEY", tt)
81+
if (index && !is.null(tt<-indices(DT))) set(list_info, extra_row, "INDICES", tt)
82+
}
83+
}
84+
}
85+
}
86+
}
87+
88+
info = NULL
89+
if (length(w)) {
90+
info = data.table(NAME=names[w], NROW=0L, NCOL=0L, MB=0.0, COLS=list(), KEY=list(), INDICES=list())
91+
for (i in seq_along(w)) { # avoid rbindlist(lapply(DT_names)) in case of a large number of tables
92+
DT = obj[[w[i]]]
93+
set(info, i, "NROW", nrow(DT))
94+
set(info, i, "NCOL", ncol(DT))
95+
if (is.function(mb)) set(info, i, "MB", as.integer(mb(DT)/1048576L)) # i.e. 1024**2
96+
if (!is.null(tt<-names(DT))) set(info, i, "COLS", tt) # TODO: don't need these if()s when #5526 is done
97+
if (!is.null(tt<-key(DT))) set(info, i, "KEY", tt)
98+
if (index && !is.null(tt<-indices(DT))) set(info, i, "INDICES", tt)
99+
}
100+
}
101+
102+
if (!is.null(list_info) && nrow(list_info)) {
103+
if (is.null(info)) {
104+
info = list_info
105+
} else {
106+
info = rbind(info, list_info)
107+
}
108+
}
109+
110+
if (is.null(info) || !nrow(info)) {
31111
if (!silent) catf("No objects of class data.table exist in %s\n", if (identical(env, .GlobalEnv)) ".GlobalEnv" else format(env))
32112
return(invisible(data.table(NULL)))
33113
}
34-
info = data.table(NAME=names[w], NROW=0L, NCOL=0L, MB=0.0, COLS=list(), KEY=list(), INDICES=list())
35-
for (i in seq_along(w)) { # avoid rbindlist(lapply(DT_names)) in case of a large number of tables
36-
DT = obj[[w[i]]]
37-
set(info, i, "NROW", nrow(DT))
38-
set(info, i, "NCOL", ncol(DT))
39-
if (is.function(mb)) set(info, i, "MB", as.integer(mb(DT)/1048576L)) # i.e. 1024**2
40-
if (!is.null(tt<-names(DT))) set(info, i, "COLS", tt) # TODO: don't need these if()s when #5526 is done
41-
if (!is.null(tt<-key(DT))) set(info, i, "KEY", tt)
42-
if (index && !is.null(tt<-indices(DT))) set(info, i, "INDICES", tt)
43-
}
44114
if (!is.function(mb)) info[,MB:=NULL]
45115
if (!index) info[,INDICES:=NULL]
46116
if (!order.col %chin% names(info)) stopf("order.col='%s' not a column name of info", order.col)

0 commit comments

Comments
 (0)