rlistfunctionapply

Apply function to list depending on values in another list


This is probably a duplicate, but I don't seem to find this specific case.

Say I have two lists:

list1 <- as.list(c(5, 8, 9))
list2 <- as.list(c(8, 10, 11))

I know how to apply a function to one list. Say I want to apply the following to list1:

lapply(list1, function(x){x+100})

But what if I only want to apply such function to list1 when the corresponding value in list2 is >=10? So that my result is:

[[1]]
[1] 5

[[2]]
[1] 108

[[3]]
[1] 109

And even more, how can I sum 100 to the value in list1 and subtract the value in list2 only when the value in list2 is >=10?

Something like the following, which obviously does not work:

lapply(list1, list2, function(x,y){if (y>=10) x+100-y})

Thanks!


Solution

  • I think you're looking for Map(), which is mapply() without simplification:

    mapply is a multivariate version of sapply. mapply applies FUN to the first elements of each ... argument, the second elements, the third elements, and so on.

    For reasons that I imagine are only known to the R devs, unlike lapply(), sapply() and tapply(), the function is the first argument of mapply() and Map().

    Map(
        \(x1, x2) if (x2 >= 10) x1 + 100 else x1,
        list1,
        list2
    )
    # [[1]]
    # [1] 5
    
    # [[2]]
    # [1] 108
    
    # [[3]]
    # [1] 109
    

    If you want to be fancy you could remove the if() statement and define the function as \(x1, x2) x1 + 100 * (x2 >= 10) but personally I think the lack of explicitness makes it less comprehensible.

    Of course you could also do this with ifelse(list2 >= 10, unlist(list1) + 100, list1) in this case but Map() is more general.

    Your second example could be expressed as Map(\(x, y) if (y >= 10) x + 100 - y else x, list1, list2).