Skip to content

Commit

Permalink
fix #66 added two new functions build_array and build_object for doin…
Browse files Browse the repository at this point in the history
…g [] and {} work

fix #65 changed select() to now do filtering, what jq select actually does - instead of object construction
bumped patch version
updated tetss and readme with new syntax
  • Loading branch information
sckott committed Mar 6, 2018
1 parent 4c0f49f commit c161c8e
Show file tree
Hide file tree
Showing 14 changed files with 308 additions and 87 deletions.
2 changes: 1 addition & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Description: Client for 'jq', a 'JSON' processor (<https://stedolan.github.io/jq
written in C. 'jq' allows the following with 'JSON' data: index into, parse,
do calculations, cut up and filter, change key names and values, perform
conditionals and comparisons, and more.
Version: 1.0.0.9140
Version: 1.0.1.9210
Depends:
R (>= 3.1.2)
License: MIT + file LICENSE
Expand Down
4 changes: 4 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ export(allj)
export(anyj)
export(at)
export(at_)
export(build_array)
export(build_array_)
export(build_object)
export(build_object_)
export(combine)
export(contains)
export(contains_)
Expand Down
17 changes: 0 additions & 17 deletions R/actions.R

This file was deleted.

73 changes: 73 additions & 0 deletions R/constructors.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#' Build arrays and objects
#'
#' @name build
#' @template args
#' @examples
#' ## BUILD ARRAYS
#' x <- '{"user":"stedolan", "projects": ["jq", "wikiflow"]}'
#' jq(x, "[.user, .projects[]]")
#' x %>% build_array(.user, .projects[])
#'
#' jq('[1, 2, 3]', '[ .[] | . * 2]')
#' '[1, 2, 3]' %>% build_array(.[] | . * 2)
#'
#'
#' ## BUILD OBJECTS
#' '{"foo": 5, "bar": 7}' %>% build_object(a = .foo) %>% peek
#' '{"foo": 5, "bar": 7}' %>% build_object(a = .foo)
#'
#' # using json dataset, just first element
#' x <- commits %>% index(0)
#' x %>%
#' build_object(message = .commit.message, name = .commit.committer.name)
#' x %>% build_object(sha = .commit.tree.sha, author = .author.login)
#'
#' # using json dataset, all elements
#' x <- index(commits)
#' x %>% build_object(message = .commit.message, name = .commit.committer.name)
#' x %>% build_object(sha = .sha, name = .commit.committer.name)
#'
#' # many JSON inputs
#' '{"foo": 5, "bar": 7} {"foo": 50, "bar": 7} {"foo": 500, "bar": 7}' %>%
#' build_object(hello = .foo)

#' @export
#' @rdname build
build_array <- function(.data, ...) {
build_array_(.data, .dots = lazyeval::lazy_dots(...))
}

#' @export
#' @rdname build
build_array_ <- function(.data, ..., .dots) {
pipe_autoexec(toggle = TRUE)
tmp <- lazyeval::all_dots(.dots, ...)
tmp <- lapply(tmp, function(x) deparse(x$expr))
z <- paste0("[", paste0(tmp, collapse = ", "), "]")
dots <- comb(tryargs(.data), structure(z, type = "array"))
structure(list(data = getdata(.data), args = dots), class = "jqr")
}


#' @export
#' @rdname build
build_object <- function(.data, ...) {
build_object_(.data, .dots = lazyeval::lazy_dots(...))
}

#' @export
#' @rdname build
build_object_ <- function(.data, ..., .dots) {
pipe_autoexec(toggle = TRUE)
tmp <- lazyeval::all_dots(.dots, ...)
vals <- unname(Map(function(x,y) {
if (nchar(x) == 0) {
as.character(y$expr)
} else {
sprintf("%s: %s", x, as.character(y$expr))
}
}, names(tmp), tmp))
z <- paste0("{", paste0(vals, collapse = ", "), "}")
dots <- comb(tryargs(.data), structure(z, type = "object"))
structure(list(data = getdata(.data), args = dots), class = "jqr")
}
4 changes: 2 additions & 2 deletions R/recurse.R
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
#' {"name": "/home", "children": [
#' {"name": "/home/stephen", "children": [
#' {"name": "/home/stephen/jq", "children": []}]}]}]}'
#' x %>% recurse(.children[]) %>% select(name)
#' x %>% recurse(.children[]) %>% select(name) %>% string
#' x %>% recurse(.children[]) %>% build_object(name)
#' x %>% recurse(.children[]) %>% build_object(name) %>% string
recurse <- function(.data, ...) {
recurse_(.data, .dots = lazyeval::lazy_dots(...))
}
Expand Down
68 changes: 41 additions & 27 deletions R/select.R
Original file line number Diff line number Diff line change
@@ -1,25 +1,34 @@
#' Select variables
#' Select - filtering
#'
#' The function \code{select(foo)} produces its input unchanged if
#' \code{foo} returns TRUE for that input, and produces no output otherwise
#'
#' @export
#' @template args
#' @note this function has changed what it does dramatically. we were
#' using this function for object construction, which is now done with
#' \code{\link{build_object}}
#' @examples
#' '{"foo": 5, "bar": 7}' %>% select(a = .foo) %>% peek
#' '{"foo": 5, "bar": 7}' %>% select(a = .foo)
#'
#' # using json dataset, just first element
#' x <- commits %>% index(0)
#' x %>%
#' select(message = .commit.message, name = .commit.committer.name)
#' x %>% select(sha = .commit.tree.sha, author = .author.login)
#'
#' # using json dataset, all elements
#' x <- index(commits)
#' x %>% select(message = .commit.message, name = .commit.committer.name)
#' x %>% select(sha = .sha, name = .commit.committer.name)
#'
#' # many JSON inputs
#' '{"foo": 5, "bar": 7} {"foo": 50, "bar": 7} {"foo": 500, "bar": 7}' %>%
#' select(hello = .foo)
#' jq('[1,5,3,0,7]', 'map(select(. >= 2))')
#' '[1,5,3,0,7]' %>% map(select(. >= 2))
#'
#'
#' '{"foo": 4, "bar": 7}' %>% select(.foo == 4)
#' '{"foo": 5, "bar": 7} {"foo": 4, "bar": 7}' %>% select(.foo == 4)
#' '[{"foo": 5, "bar": 7}, {"foo": 4, "bar": 7}]' %>% index() %>%
#' select(.foo == 4)
#' '{"foo": 4, "bar": 7} {"foo": 5, "bar": 7} {"foo": 8, "bar": 7}' %>%
#' select(.foo < 6)
#'
#' x <- '{"foo": 4, "bar": 2} {"foo": 5, "bar": 4} {"foo": 8, "bar": 12}'
#' jq(x, 'select((.foo < 6) and (.bar > 3))')
#' jq(x, 'select((.foo < 6) or (.bar > 3))')
#' x %>% select((.foo < 6) && (.bar > 3))
#' x %>% select((.foo < 6) || (.bar > 3))
#'
#' x <- '[{"foo": 5, "bar": 7}, {"foo": 4, "bar": 7}, {"foo": 4, "bar": 9}]'
#' jq(x, '.[] | select(.foo == 4) | {user: .bar}')
#' x %>% index() %>% select(.foo == 4) %>% build_object(user = .bar)
select <- function(.data, ...) {
select_(.data, .dots = lazyeval::lazy_dots(...))
}
Expand All @@ -29,14 +38,19 @@ select <- function(.data, ...) {
select_ <- function(.data, ..., .dots) {
pipe_autoexec(toggle = TRUE)
tmp <- lazyeval::all_dots(.dots, ...)
vals <- unname(Map(function(x,y) {
if (nchar(x) == 0) {
as.character(y$expr)
} else {
sprintf("%s: %s", x, as.character(y$expr))
}
}, names(tmp), tmp))
z <- paste0("{", paste0(vals, collapse = ", "), "}")
dots <- comb(tryargs(.data), structure(z, type = "select"))
z <- paste0(unlist(lapply(tmp, function(x) {
sub_ops_sel(sub_ops(deparse(x$expr)))
})), collapse = ", ")
dots <- comb(tryargs(.data), structure(sprintf("select(%s)", z),
type = "select"))
structure(list(data = getdata(.data), args = dots), class = "jqr")
}

sub_ops_sel <- function(x) {
ops <- c("&&", "\\|\\|")
use <- c("and", "or")
if (base::any(vapply(ops, grepl, logical(1), x = x))) {
for (i in seq_along(ops)) x <- gsub(ops[[i]], use[[i]], x)
}
return(x)
}
2 changes: 1 addition & 1 deletion R/vars.R
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
#' x %>% dotstr(posts[])
#' x %>% dotstr(posts[]) %>% string
#' x %>% vars(realnames = names) %>% dotstr(posts[]) %>%
#' select(title, author = "$names[.author]")
#' build_object(title, author = "$names[.author]")
vars <- function(.data, ...) {
vars_(.data, .dots = lazyeval::lazy_dots(...))
}
Expand Down
34 changes: 28 additions & 6 deletions README.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ Show the query to be used using `peek()`
x <- '{"user":"stedolan","titles":["JQ Primer", "More JQ"]}'
jq(x, '{user, title: .titles[]}')
x %>% index()
x %>% select(user, title = `.titles[]`)
x %>% build_object(user, title = `.titles[]`)
jq(x, '{user, title: .titles[]}') %>% jsonlite::toJSON() %>% jsonlite::validate()
```

Expand Down Expand Up @@ -236,6 +236,28 @@ unique
'[1,2,5,3,5,3,1,3]' %>% uniquej
```


#### filter

With filtering via `select()` you can use various operators, like `==`,
`&&`, `||`. We translate these internally for you to what `jq` wants
to see (`==`, `and`, `or`).

Simple, one condition

```{r}
'{"foo": 4, "bar": 7}' %>% select(.foo == 4)
```

More complicated. Combine more than one condition; combine each individual
filtering task in parentheses

```{r}
x <- '{"foo": 4, "bar": 2} {"foo": 5, "bar": 4} {"foo": 8, "bar": 12}'
x %>% select((.foo < 6) && (.bar > 3))
x %>% select((.foo < 6) || (.bar > 3))
```

#### types

get type information for each element
Expand Down Expand Up @@ -274,18 +296,18 @@ str3 %>% haskey(2)
str3 %>% haskey(1,2)
```

Select variables by name, and rename
Build an object, selecting variables by name, and rename

```{r}
'{"foo": 5, "bar": 7}' %>% select(a = .foo)
'{"foo": 5, "bar": 7}' %>% build_object(a = .foo)
```

More complicated `select()`, using the included dataset `commits`
More complicated `build_object()`, using the included dataset `commits`

```{r}
commits %>%
index() %>%
select(sha = .sha, name = .commit.committer.name)
build_object(sha = .sha, name = .commit.committer.name)
```

#### Maths
Expand Down Expand Up @@ -356,7 +378,7 @@ This outputs a few pieces of JSON
```{r}
(x <- commits %>%
index() %>%
select(sha = .sha, name = .commit.committer.name))
build_object(sha = .sha, name = .commit.committer.name))
```

Use `combine()` to put them together.
Expand Down
Loading

0 comments on commit c161c8e

Please sign in to comment.