Nyiannos
Nyiannos

Reputation: 99

Shuffling around elements in a list

My general question concerns shuffling elements around in a list efficiently.

Say I have a list:

region <- list(c(1,3,2,6),c(5,8,9),c(10,4,7))

and two constants:

value <- 2
swapin <- 5

I want to do two things. I want to remove the element == value from the vector in the list, and then add it to the vector in which the first element of that vector == swapin

The result should look like:

region <- list(c(1,3,6),c(5,8,9,2),c(10,4,7))

For the first step, the only way I can think of doing it is doing something like this:

region <- lapply(1:length(region), function(x) region[[x]][region[[x]] != value])

but this seems inefficient. My actual data could involve a very large list, and this approach seems cumbersome. Is there an easy trick to avoiding the looping going on?

For the second step, I can create an updated vector like this:

updated <- c(unlist(region[sapply(region, `[`, 1)==swap]),best)

but I am stumped on how to replace the vector currently in the list, c(5,8,9), with the updated vector, c(5,8,9,2). Maybe I can just add the element some easier way?

Can anyone help, please?

Upvotes: 2

Views: 63

Answers (1)

acylam
acylam

Reputation: 18681

Something like this will do the trick:

region <- list(c(1,3,2,6),c(5,8,9),c(10,4,7))

value <- 2
swapin <- 5

step1 = lapply(region, function(x) x[x != value])

step2 = lapply(step1, function(x){
  if(x[1]==swapin){
    return(c(x, value))
  } else {
    return(x)
  }
})

Instead of looping through region by feeding in it's element indices, you can just loop through region itself. This is actually how lapply is intended to be used - to apply a function to each element of a list. The second step replaces each element x, with x + value if the first element of x matches with swapin, or with x itself if swapin doesn't match.

Result:

> step2
[[1]]
[1] 1 3 6

[[2]]
[1] 5 8 9 2

[[3]]
[1] 10  4  7

You can also easily make it a convenience function for later use:

element_swap = function(list, value, swapin){

  step1 = lapply(list, function(x) x[x != value])

  step2 = lapply(step1, function(x){
    if(x[1]==swapin){
      return(c(x, value))
    } else {
      return(x)
    }
  })

  return(step2)

}

Result:

> element_swap(region, 1, 10)
[[1]]
[1] 3 2 6

[[2]]
[1] 5 8 9

[[3]]
[1] 10  4  7  1

Upvotes: 1

Related Questions