If performance is a consideration, the best way I have found for this is
length(x) + 1L - match(TRUE, rev(x))
This is much faster, especially in the general case when one person has the right to the rightmost match for more than one entry.
MatchLast <- function (needles, haystack) # This approach
length(haystack) + 1L - match(needles, rev(haystack))
MaxWhich <- function (needles, haystack) # Ronak Shah approach
vapply(needles, function (needle) max(which(haystack==needle)), integer(1))
Pos <- function (needles, haystack) # thelatemail suggestion
vapply(needles, function (needle)
Position(function (x) x == needle, haystack, right=TRUE),
integer(1))
Tail <- function (needles, haystack) # akrun solution
vapply(needles, function (needle) tail(which(haystack==needle), 1), integer(1))
With Rilkon42 data:
x <- c(TRUE, FALSE, TRUE, FALSE, FALSE)
microbenchmark(MatchLast(TRUE, x), MaxWhich(TRUE, x), Pos(TRUE, x), Tail(TRUE, x))
## function min lq mean median uq max
## MatchLast 10.730 19.1270 175.3851 23.7920 28.458 14757.131
## MaxWhich 11.663 22.1600 275.4657 25.1920 28.224 24355.120
## Pos 25.192 47.5845 194.1296 52.7160 64.612 12890.622
## Tail 39.187 69.7435 223.1278 83.0395 101.233 9223.848
In a more general case:
needles <- 24:45
haystack <- c(45, 45, 44, 44, 43, 43, 42, 42, 41, 41, 40, 40, 39, 39, 38, 38, 37, 37,
36, 36, 35, 35, 34, 34, 33, 33, 32, 32, 31, 31, 30, 30, 29, 29, 28, 28,
27, 27, 26, 26, 25, 25, 24, 24)
microbenchmark(MatchLast(needles, haystack), MaxWhich(needles, haystack),
Pos(needles, haystack), Tail(needles, haystack))
## function min lq mean median uq max
## MatchLast 15.395 30.3240 137.3086 36.8550 48.051 9842.441
## MaxWhich 90.971 102.1665 161.1100 172.3765 214.829 238.854
## Pos 709.563 733.8220 1111.7000 1162.7780 1507.530 1645.383
## Tail 654.981 690.2035 1017.7400 882.6385 1404.197 1595.933