From 2d64375d059a20773ba0233ed2ab6590cbb6a8c8 Mon Sep 17 00:00:00 2001 From: timelyportfolio Date: Tue, 1 Nov 2016 08:25:30 -0500 Subject: [PATCH] add helper number_unnamed function (see #18) --- NAMESPACE | 1 + NEWS.md | 3 ++- R/utils.R | 57 ++++++++++++++++++++++++++++++++++++++++++- man/number_unnamed.Rd | 28 +++++++++++++++++++++ man/recurse.Rd | 21 ++++++++++++++++ 5 files changed, 108 insertions(+), 2 deletions(-) create mode 100644 man/number_unnamed.Rd create mode 100644 man/recurse.Rd diff --git a/NAMESPACE b/NAMESPACE index ed14e80..65c88f7 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -3,6 +3,7 @@ export(jsonedit) export(jsoneditOutput) export(jsonedit_gadget) +export(number_unnamed) export(reactjson) export(reactjsonOutput) export(renderJsonedit) diff --git a/NEWS.md b/NEWS.md index 7edb0a3..49bd263 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,7 +1,8 @@ # listviewer 1.4.0 * add `elementId` to the `jsonedit` function -* update `react-json` to [`0.2.1`] +* update `react-json` to [`0.2.1`](https://github.com/arqex/react-json/releases/tag/0.2.1) +* add helper `number_unnamed` function (see [issue](https://github.com/timelyportfolio/listviewer/issues/18)) # listviewer 1.3 diff --git a/R/utils.R b/R/utils.R index 3370913..6c15c21 100644 --- a/R/utils.R +++ b/R/utils.R @@ -1,5 +1,4 @@ #' @keywords internal - named_vec2list <- function(listx){ # to avoid toJSON keep_vec_names warnings # with named vectors @@ -22,3 +21,59 @@ list_proper_form <- function(listdata){ } } +#' Recurse Over Nested Lists +#' +#' Like \code{rapply} but recurses over nested lists and +#' retain \code{attributes} and \code{names}. +#' +#' @param l \code{list} over which we would like to recurse +#' @param func \code{function} to apply to the list +#' @param ... arguments for the \code{func} +#' +#' @keywords internal +recurse <- function(l, func, ...) { +l <- func(l, ...) +if(is.list(l) && length(l)>0){ + lapply( + l, + function(ll){ + recurse(ll, func, ...) + } + ) +} else { + l +} +} + +#' @keywords internal +add_number_names <- function(l){ + if(length(l)>0 && is.null(names(l))){ + names(l) <- seq_len(length(l)) + } + l +} + + +#' Number Starting at \code{1} +#' +#' JavaScript starts at \code{0}, but R starts at \code{1}. +#' This means unnamed lists and vectors are indexed starting at +#' \code{0} in listviewer widgets. This little helper function +#' tries to resolve the disconnect by assigning sequential numbers +#' starting at \code{1} to names for unnamed \code{lists} and \code{vectors}. +#' Please note though that using \code{number_unnamed} will potentially +#' cause difficulties serializing back and forth between JavaScript and R. +#' +#' @param l \code{list} +#' +#' @examples +#' library(listviewer) +#' jsonedit( +#' number_unnamed(list(x=list(letters[1:3]))) +#' ) +#' +#' @export + +number_unnamed <- function(l) { + recurse(l, add_number_names) +} diff --git a/man/number_unnamed.Rd b/man/number_unnamed.Rd new file mode 100644 index 0000000..e5753a8 --- /dev/null +++ b/man/number_unnamed.Rd @@ -0,0 +1,28 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/utils.R +\name{number_unnamed} +\alias{number_unnamed} +\title{Number Starting at \code{1}} +\usage{ +number_unnamed(l) +} +\arguments{ +\item{l}{\code{list}} +} +\description{ +JavaScript starts at \code{0}, but R starts at \code{1}. +This means unnamed lists and vectors are indexed starting at +\code{0} in listviewer widgets. This little helper function +tries to resolve the disconnect by assigning sequential numbers +starting at \code{1} to names for unnamed \code{lists} and \code{vectors}. +Please note though that using \code{number_unnamed} will potentially +cause difficulties serializing back and forth between JavaScript and R. +} +\examples{ +library(listviewer) +jsonedit( + number_unnamed(list(x=list(letters[1:3]))) +) + +} + diff --git a/man/recurse.Rd b/man/recurse.Rd new file mode 100644 index 0000000..c4c766d --- /dev/null +++ b/man/recurse.Rd @@ -0,0 +1,21 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/utils.R +\name{recurse} +\alias{recurse} +\title{Recurse Over Nested Lists} +\usage{ +recurse(l, func, ...) +} +\arguments{ +\item{l}{\code{list} over which we would like to recurse} + +\item{func}{\code{function} to apply to the list} + +\item{...}{arguments for the \code{func}} +} +\description{ +Like \code{rapply} but recurses over nested lists and +retain \code{attributes} and \code{names}. +} +\keyword{internal} +