I have the following vectors example:
v1 <- c("AA", "BB")
v2 <- c("AA", "BB", "CCC")
Note that the length of each vector can be varied.
What I want to do is to interleave each vector with a string:
linker <- "xxx"
Resulting in this:
c("AA", "xxx", "BB")
c("AA","xxx", "BB", "xxx", "CCC")
How can I achieve that?
You could use an rbind trick here:
v1 <- c("AA", "BB")
v2 <- c("AA", "BB", "CCC")
linker <- "xxx"
head(c(rbind(v2, linker)), -1)
[1] "AA" "xxx" "BB" "xxx" "CCC"
We can try strsplit + paste0 like below
> strsplit(paste0(v2, collapse = sprintf(" %s ", linker)), " ")[[1]]
[1] "AA" "xxx" "BB" "xxx" "CCC"
Here you have a possible answer:
v1 <- c("AA", "BB")
v2 <- c("AA", "BB", "CCC")
linker <- "xxx"
interleave <- function(v,l){
result <- c()
for(i in 1:length(v)){
if(i!=1){
result <- c(result,l,v[i])
}else{
result <- c(result,v[i])
}
}
return(result)
}
interleave(v1,linker)
interleave(v2,linker)
Results:
> interleave(v1,linker)
[1] "AA" "xxx" "BB"
>
> interleave(v2,linker)
[1] "AA" "xxx" "BB" "xxx" "CCC"
We can use append, and then head to remove the trailing linker:
append_linker <- function(vector, linker){
lapply(vector, \(x) append(x, linker)) |>
unlist() |>
head(-1)
}
append_linker(v1, linker)
[1] "AA" "xxx" "BB"
append_linker(v2, linker)
[1] "AA" "xxx" "BB" "xxx" "CCC"
A creative application of mapply and c:
v1 <- c("AA", "BB")
v2 <- c("AA", "BB", "CCC")
linker <- 'xxx'
c(mapply(c, linker, v1))[-1]
[1] "AA" "xxx" "BB"
c(mapply(c, linker, v2))[-1]
[1] "AA" "xxx" "BB" "xxx" "CCC"
Related
I have a list with named elements, called namedlist.
I want to select some of the elements based on their names, as stored in a vector.
This post tells me how to do it to select a single element:
namedlist <- list(c("fff", "gggg", "hhh"), c("xxx", "yyy", "zzz"), c("pp", "ooo"), c("lll"))
names(namedlist) <- c("AA", "BB", "CC", "DD")
# only select the element AA
namedlist[grep("AA", names(namedlist))]
However, I want to select multiple elements from that list.
I have the names of the elements I want to select stored in a vector, needed.
needed <- c("AA", "DD")
However, the following code does not work:
namedlist[grep(needed, names(namedlist))]
How can I do that?
Thanks for your help!
Use subscripting:
namedlist[needed]
## $AA
## [1] "fff" "gggg" "hhh"
##
## $DD
## [1] "lll"
namedlist$AA
## [1] "fff" "gggg" "hhh"
namedlist[["AA"]] # same
## [1] "fff" "gggg" "hhh"
namedlist["AA"] # same except it returns a sublist
## $AA
## [1] "fff" "gggg" "hhh"
I'm new to R and looking for the following:
My input:
v = list(bob=c("aa", "cc"), cas=c("tt", "ff"), john=c("aa", "bb"))
v
$bob
[1] "aa" "cc"
$cas
[1] "tt" "ff"
$john
[1] "aa" "bb"
I want to sort based on the character vectors inside it, the desired output I'm looking for :
sorted_v
$john
[1] "aa" "bb"
$bob
[1] "aa" "cc"
$cas
[1] "tt" "ff"
How to obtain sorted_v?
We can paste all the elements of the list together, sort them and extract the names of them.
sorted_v <- v[names(sort(sapply(v, paste0, collapse = "")))]
sorted_v
#$john
#[1] "aa" "bb"
#$bob
#[1] "aa" "cc"
#$cas
#[1] "tt" "ff"
OR
as #ycw mentioned in the comments we can also use toString instead of paste0, collapse combination :
sorted_v <- v[names(sort(sapply(v, toString)))]
Also using #A5C1D2H2I1M1N2O1R2T1 and #ycw's inputs we can reduce it to
v[order(sapply(v, toString))]
#$john
#[1] "aa" "bb"
#$bob
#[1] "aa" "cc"
#$cas
#[1] "tt" "ff"
This question has been asked for other languages but I'm looking for the most idiomatic way to find all strings of length k that can be formed from a set of n characters in R
Example input and output:
input <- c('a', 'b')
output <- c('aa', 'ab', 'ba', 'bb')
A little more complicated than I'd like. I think outer() only works for n=2. combn doesn't include repeats.
allcomb <- function(input = c('a', 'b'), n=2) {
args <- rep(list(input),n)
gr <- do.call(expand.grid,args)
return(do.call(paste0,gr))
}
Thanks to #thelatemail for improvements ...
allcomb(n=4)
## [1] "aaaa" "baaa" "abaa" "bbaa" "aaba" "baba" "abba"
## [8] "bbba" "aaab" "baab" "abab" "bbab" "aabb" "babb"
## [15] "abbb" "bbbb"
Adapting AK88's answer, outer can be used for arbitrary values of k, although it's not necessarily the most efficient solution:
input <- c('a', 'b')
k = 5
perms = input
for (i in 2:k) {
perms = outer(perms, input, paste, sep="")
}
result = as.vector(perms)
m <- outer(input, input, paste, sep="")
output = as.vector(m)
## "aa" "ba" "ab" "bb"
I'm not proud of how this looks, but it works...
allcombs <- function(x, k) {
apply(expand.grid(split(t(replicate(k, x)), seq_len(k))), 1, paste, collapse = "")
}
allcombs(letters[1:2], 2)
#> [1] "aa" "ba" "ab" "bb"
allcombs(letters[1:2], 4)
#> [1] "aaaa" "baaa" "abaa" "bbaa" "aaba" "baba" "abba" "bbba" "aaab" "baab"
#> [11] "abab" "bbab" "aabb" "babb" "abbb" "bbbb"
I want to arrange a list with characters based on order/arrange results on another list.
For example, given a list char, and list of values (numbers) mini, I can get sorted char list:
sorted<-mapply(function(x, y) y[x], lapply(mini, order), char)
I want to use arrange/order that will sort char list based on ascending min list
(I want to have ascendant alphabetical char when values in mini are same).
Suggestions?
EDIT: dummy example
char <- list(A=c("dd", "aa", "cc", "ff"), B=c("rr", "ee", "tt", "aa"))
mini <- list(A=c(4,2,4,4), B=c(5,5,7,1))
char
$A
"dd" "aa" "cc" "ff" ...
$B
"rr" "ee" "tt" "aa" ...
mini
$A
4 2 4 4 ...
$B
5 5 7 1 ...
expected result:
sorted
$A
"aa" "cc" "dd" "ff"
$B
"aa" "ee" "rr" "tt"
Try this:
Map(function(x, y) y[order(x, y)], mini, char)
lapply( names(char), function(nm) char[[nm]][order(mini[[nm]], char[[nm]])])
#------
[[1]]
[1] "aa" "cc" "dd" "ff"
[[2]]
[1] "aa" "ee" "rr" "tt"
I try to append chars, but i always get a gap between them.
Instead of: "ab" i get "a b" for example.
I tried: append and paste.
paste("a", "b")
[1] "a b"
paste("a", "b", sep="")
[1] "ab"
paste0("a", "b")
[1] "ab"
use collapse=""
paste(c("a", "b"), collapse="")
# [1] "ab"
or paste0:
paste0("a", "b")
# [1] "ab"
(which is short for paste("a", "b", sep=""))
Another option would be sprintf:
sprintf("%s%s", "a", "b")
# [1] "ab"