Skip to content

Commit d8e8cd3

Browse files
authored
Implement str_flatten_comma() (#464)
Special case of `str_flatten()` that can automatically handle the Oxford comma with 2 elements.
1 parent f6d9c25 commit d8e8cd3

File tree

5 files changed

+68
-12
lines changed

5 files changed

+68
-12
lines changed

NAMESPACE

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ export(str_escape)
2727
export(str_extract)
2828
export(str_extract_all)
2929
export(str_flatten)
30+
export(str_flatten_comma)
3031
export(str_glue)
3132
export(str_glue_data)
3233
export(str_interp)

NEWS.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@
4343

4444
* `str_extract()` can now optionally extract a capturing group instead of
4545
the complete match (#420).
46+
47+
* `str_flatten_comma()` is a special case of `str_flatten()` designed for
48+
comman separated flattening and can handle the special case of Oxford
49+
commas with two elements (#444).
4650

4751
* New `str_split_1()` is tailored for the special case of splitting up a single
4852
string (#409).

R/flatten.R

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
11
#' Flatten a string
2+
#
3+
#' @description
4+
#' `str_flatten()` reduces a character vector to a single string. This is a
5+
#' summary function because regardless of the length of the input `x`, it
6+
#' always returns a single string.
27
#'
3-
#' Reduce a character vector to a single string. This is a summary function
4-
#' because regardless of the length of the input `x`, it always returns a
5-
#' single string.
8+
#' `str_flatten_comma()` is a variation designed specifically for flattening
9+
#' with commas. It automatically recognises if `last` uses the Oxford comma
10+
#' and handles the special case of 2 elements.
611
#'
712
#' @inheritParams str_detect
813
#' @param collapse String to insert between each piece. Defaults to `""`.
@@ -15,11 +20,20 @@
1520
#' str_flatten(letters)
1621
#' str_flatten(letters, "-")
1722
#'
18-
#' str_flatten(letters[1:4], ", ", ", and ")
23+
#' str_flatten(letters[1:3], ", ")
24+
#'
25+
#' # Use last to customise the last component
26+
#' str_flatten(letters[1:3], ", ", " and ")
27+
#'
28+
#' # this almost works if you want an Oxford (aka serial) comma
1929
#' str_flatten(letters[1:3], ", ", ", and ")
30+
#'
31+
#' # but it will always add a comma, even when not necessary
2032
#' str_flatten(letters[1:2], ", ", ", and ")
21-
#' str_flatten(letters[1], ", ", ", and ")
22-
#' str_flatten(letters[0], ", ", ", and ")
33+
#'
34+
#' # str_flatten_comma knows how to handle the Oxford comma
35+
#' str_flatten_comma(letters[1:3], ", and ")
36+
#' str_flatten_comma(letters[1:2], ", and ")
2337
str_flatten <- function(string, collapse = "", last = NULL, na.rm = FALSE) {
2438
check_string(collapse)
2539
check_string(last, allow_null = TRUE)
@@ -39,3 +53,16 @@ str_flatten <- function(string, collapse = "", last = NULL, na.rm = FALSE) {
3953

4054
stri_flatten(string, collapse = collapse)
4155
}
56+
57+
#' @export
58+
#' @rdname str_flatten
59+
str_flatten_comma <- function(string, last = NULL, na.rm = FALSE) {
60+
check_string(last, allow_null = TRUE)
61+
check_bool(na.rm)
62+
63+
# Remove comma if exactly two elements, and last uses Oxford comma
64+
if (length(string) == 2 && !is.null(last) && str_detect(last, "^,")) {
65+
last <- str_replace(last, "^,", "")
66+
}
67+
str_flatten(string, ", ", last = last, na.rm = na.rm)
68+
}

man/str_flatten.Rd

Lines changed: 22 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/testthat/test-flatten.R

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,11 @@ test_that("can remove missing values", {
1616
expect_equal(str_flatten(c("a", NA)), NA_character_)
1717
expect_equal(str_flatten(c("a", NA), na.rm = TRUE), "a")
1818
})
19+
20+
test_that("str_flatten_oxford removes comma iif necessary", {
21+
expect_equal(str_flatten_comma(letters[1:2], ", or "), "a or b")
22+
23+
expect_equal(str_flatten_comma(letters[1:3], ", or "), "a, b, or c")
24+
expect_equal(str_flatten_comma(letters[1:3], " or "), "a, b or c")
25+
expect_equal(str_flatten_comma(letters[1:3]), "a, b, c")
26+
})

0 commit comments

Comments
 (0)