Reputation: 22205
If I have a vector of type character, how can I concatenate the values into string? Here's how I would do it with paste():
sdata = c('a', 'b', 'c')
paste(sdata[1], sdata[2], sdata[3], sep ='')
yielding "abc"
.
But of course, that only works if I know the length of sdata ahead of time.
Upvotes: 359
Views: 422676
Reputation: 18732
The stringr
package has a few, fast ways you could accomplish this.
str_flatten
By default will collapse your character vector with no spaces, but does have collapse
argument as well:
str_flatten(sdata)
# [1] "abc"
Also has an optional last
argument to use in place of the final separator.
str_c
Similar to paste
with a collapse
argument you need to specify to accomplish this:
str_c(sdata, collapse = "")
# [1] "abc"
str_flatten_comma
New as of stringr
1.5.0 if you want a comma delimited collapse. Here the last
argument recognizes the Oxford comma:
str_flatten_comma(sdata) # similar to base R toString()
# [1] "a, b, c"
## handling Oxford comma
str_flatten_comma(sdata, last = ", and ")
# [1] "a, b, and c"
str_flatten_comma(sdata[1:2], last = ", and ") # (removes comma)
# [1] "a and b"
For most cases stringi
and stringr
will provide enough speed, but if you need something faster consider the stringfish
package:
library(stringfish)
sf_collapse(sdata, collapse = '')
# [1] "abc"
For completeness, you could use paste0
, though there is no obvious advantage here over paste
:
paste0(sdata, collapse = "")
Across vector sizes of 10K, 100K, 1M and 10M stringfish
yields consistently faster results:
expression string_length min median `itr/sec` `gc/sec` n_itr n_gc
<bch:expr> <dbl> <bch:tm> <bch:tm> <dbl> <dbl> <int> <dbl>
1 sf_collapse 10000 149µs 163.8µs 6020. 0 3009 0
2 str_flatten 10000 166.8µs 174.2µs 5527. 0 2762 0
3 stri_paste 10000 163.9µs 176µs 5517. 0 2757 0
4 str_c 10000 186µs 200.3µs 4954. 0 2476 0
5 paste 10000 606.8µs 677.4µs 1472. 2.06 715 1
6 paste0 10000 606.3µs 681.9µs 1449. 0 725 0
7 sf_collapse 100000 1.48ms 1.55ms 643. 0 322 0
8 stri_paste 100000 1.81ms 1.96ms 490. 0 245 0
9 str_flatten 100000 1.81ms 2.04ms 486. 0 244 0
10 str_c 100000 1.84ms 2.03ms 480. 0 241 0
11 paste0 100000 6.24ms 6.73ms 147. 2.10 70 1
12 paste 100000 6.37ms 6.98ms 142. 0 72 0
13 sf_collapse 1000000 16.02ms 16.88ms 59.4 0 30 0
14 str_flatten 1000000 19.45ms 20.02ms 49.7 0 25 0
15 stri_paste 1000000 19.28ms 20.07ms 49.6 0 25 0
16 str_c 1000000 19.8ms 20.77ms 47.9 0 24 0
17 paste 1000000 64.06ms 65.41ms 15.3 0 8 0
18 paste0 1000000 64.54ms 65.75ms 15.1 0 8 0
19 sf_collapse 10000000 167.88ms 169.53ms 5.91 0 3 0
20 str_c 10000000 199.67ms 200.04ms 4.96 0 3 0
21 stri_paste 10000000 205.17ms 210.69ms 4.76 0 3 0
22 str_flatten 10000000 216.98ms 217.04ms 4.60 0 3 0
23 paste0 10000000 690.85ms 690.85ms 1.45 0 1 0
24 paste 10000000 767.12ms 767.12ms 1.30 1.30 1 1
Benchmark Code
library(bench)
library(stringr)
library(stringi)
library(stringfish)
set.seed(4)
results <- press(
string_length = c(1E4, 1E5, 1E6, 1E7),
{
x <- sample(letters, string_length, replace = T)
mark(
stri_paste = stri_paste(x, collapse=''),
paste = paste(x,collapse=''),
str_flatten = str_flatten(x),
str_c = str_c(x, collapse = ""),
paste0 = paste0(x, collapse = ""),
sf_collapse = sf_collapse(x, collapse = ""),
memory = FALSE)
}
)
sort_by(results, ~ list(string_length, - `itr/sec`)) |>
subset(select = c(1:5, 7:9)) |>
print(n = 24)
Upvotes: 11
Reputation: 1453
For sdata
:
gsub(", ", "", toString(sdata))
For a vector of integers:
gsub(", ", "", toString(c(1:10)))
Upvotes: 4
Reputation: 3269
Another way would be to use glue
package:
glue_collapse(glue("{sdata}"))
paste(glue("{sdata}"), collapse = '')
Upvotes: 2
Reputation: 11
Here is a little utility function that collapses a named or unnamed list of values to a single string for easier printing. It will also print the code line itself. It's from my list examples in R page.
Generate some lists named or unnamed:
# Define Lists
ls_num <- list(1,2,3)
ls_str <- list('1','2','3')
ls_num_str <- list(1,2,'3')
# Named Lists
ar_st_names <- c('e1','e2','e3')
ls_num_str_named <- ls_num_str
names(ls_num_str_named) <- ar_st_names
# Add Element to Named List
ls_num_str_named$e4 <- 'this is added'
Here is the a function that will convert named or unnamed list to string:
ffi_lst2str <- function(ls_list, st_desc, bl_print=TRUE) {
# string desc
if(missing(st_desc)){
st_desc <- deparse(substitute(ls_list))
}
# create string
st_string_from_list = paste0(paste0(st_desc, ':'),
paste(names(ls_list), ls_list, sep="=", collapse=";" ))
if (bl_print){
print(st_string_from_list)
}
}
Testing the function with the lists created prior:
> ffi_lst2str(ls_num)
[1] "ls_num:=1;=2;=3"
> ffi_lst2str(ls_str)
[1] "ls_str:=1;=2;=3"
> ffi_lst2str(ls_num_str)
[1] "ls_num_str:=1;=2;=3"
> ffi_lst2str(ls_num_str_named)
[1] "ls_num_str_named:e1=1;e2=2;e3=3;e4=this is added"
Testing the function with subset of list elements:
> ffi_lst2str(ls_num_str_named[c('e2','e3','e4')])
[1] "ls_num_str_named[c(\"e2\", \"e3\", \"e4\")]:e2=2;e3=3;e4=this is added"
> ffi_lst2str(ls_num[2:3])
[1] "ls_num[2:3]:=2;=3"
> ffi_lst2str(ls_str[2:3])
[1] "ls_str[2:3]:=2;=3"
> ffi_lst2str(ls_num_str[2:4])
[1] "ls_num_str[2:4]:=2;=3;=NULL"
> ffi_lst2str(ls_num_str_named[c('e2','e3','e4')])
[1] "ls_num_str_named[c(\"e2\", \"e3\", \"e4\")]:e2=2;e3=3;e4=this is added"
Upvotes: 1
Reputation: 24015
Matt's answer is definitely the right answer. However, here's an alternative solution for comic relief purposes:
do.call(paste, c(as.list(sdata), sep = ""))
Upvotes: 52
Reputation: 16080
You can use stri_paste
function with collapse
parameter from stringi
package like this:
stri_paste(letters, collapse='')
## [1] "abcdefghijklmnopqrstuvwxyz"
And some benchmarks:
require(microbenchmark)
test <- stri_rand_lipsum(100)
microbenchmark(stri_paste(test, collapse=''), paste(test,collapse=''), do.call(paste, c(as.list(test), sep="")))
Unit: microseconds
expr min lq mean median uq max neval
stri_paste(test, collapse = "") 137.477 139.6040 155.8157 148.5810 163.5375 226.171 100
paste(test, collapse = "") 404.139 406.4100 446.0270 432.3250 442.9825 723.793 100
do.call(paste, c(as.list(test), sep = "")) 216.937 226.0265 251.6779 237.3945 264.8935 405.989 100
Upvotes: 15
Reputation: 19025
Matt Turner's answer is definitely the right answer. However, in the spirit of Ken Williams' answer, you could also do:
capture.output(cat(sdata, sep=""))
Upvotes: 5
Reputation: 6351
Try using an empty collapse argument within the paste function:
paste(sdata, collapse = '')
Thanks to http://twitter.com/onelinetips/status/7491806343
Upvotes: 621