PeterD
PeterD

Reputation: 439

How to generate a named list containing vectors with repeating integers from a named list with character vectors in R?

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:

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

Answers (3)

Ronak Shah
Ronak Shah

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

ThomasIsCoding
ThomasIsCoding

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

Shawn Brar
Shawn Brar

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

Related Questions