Reputation: 439
Given is the list below. This list contains character vectors of variable length.
l1 <- list("a" = c("x1", "x2", "x3"),
"b" = c("x4", "x5"),
"c" = c("x6", "x7", "x8", "x9"))
> l1
$a
[1] "x1" "x2" "x3"
$b
[1] "x4" "x5"
$c
[1] "x6" "x7" "x8" "x9"
The desired output, let's call it l2
, is the following:
$a
[1] 1 1 1
$b
[1] 2 2
$c
[1] 3 3 3 3
This output has the following characteristics:
l2
is a named list in which the names of the original list l1
are preserved.l2
is the same as list l1
.l1
is preserved in l2
.l2
contains vectors with repeating integers. The length of each vector in l2
is the same as the corresponding character vector in l1
.Part of solution
I found this post in which the statement below helped me to construct a partial solution.
The usual work-around is to pass it the names or indices of the vector instead of the vector itself.
l2 <- lapply(X = seq_along(l1),
FUN = function(x) rep(x, times = length(l1[[x]])))
l2
[[1]]
[1] 1 1 1
[[2]]
[1] 2 2
[[3]]
[1] 3 3 3 3
All criteria are met, except that the names are not preserved in l2
.
How can I fix this in one go (not using a seperate statement after the lapply statement)?
Upvotes: 1
Views: 126
Reputation: 389012
You can use []
to preserve the names the list.
l1[] <- lapply(seq_along(l1), function(x) rep(x, times = length(l1[[x]])))
l1
#$a
#[1] 1 1 1
#$b
#[1] 2 2
#$c
#[1] 3 3 3 3
Another solution with Map
.
l1[] <- Map(rep, seq_along(l1), lengths(l1))
In case you want to have another objects l2
keeping l1
as it is, create a copy of l1
in l2
by doing l2 <- l1
.
Upvotes: 1
Reputation: 101663
You can try the following base R option, using lengths
+ rep
+ relist
like below
> relist(rep(seq_along(l1), lengths(l1)), l1)
$a
[1] 1 1 1
$b
[1] 2 2
$c
[1] 3 3 3 3
Upvotes: 1
Reputation: 1420
After you run your above code,, just add the code below:-
names(l2) <- names(l1)
This will assign the names of l1
to l2
, and hence, you will have the same names.
Edit: You can't achieve this with lapply
, but you can do it with sapply
by doing the following the following:-
l2 <- sapply(X = names(l1),
FUN = function(x) rep(which(names(l1) == x), times = length(l1[[x]])))
l2
$a
[1] 1 1 1
$b
[1] 2 2
$c
[1] 3 3 3 3
Turns out, if X
argument of sapply
is character
vector, it will return the list
by using X
as names of the returned list
.
Upvotes: 2