Подтвердить что ты не робот

Быстрый способ получить индекс соответствия в списке

Учитывая список a, содержащий векторы неравной длины и вектор b, содержащий некоторые элементы из векторов в a, я хочу получить вектор равной длины b, содержащий индекс в a где элемент в b соответствует (это плохое объяснение, которое я знаю)...

Следующий код выполняет задание:

a <- list(1:3, 4:5, 6:9)
b <- c(2, 3, 5, 8)

sapply(b, function(x, list) which(unlist(lapply(list, function(y, z) z %in% y, z=x))), list=a)
[1] 1 1 2 3

Замена sapply на цикл for обеспечивает то же самое, конечно,

Проблема заключается в том, что этот код будет использоваться со списком и векторами длиной более 1000. В реальном наборе времени функция занимает около 15 секунд (как для цикла цикла, так и для sapply).

У кого-нибудь есть идея, как ускорить это, безопасно для параллельного подхода? Я не видел векторный подход (и я не могу программировать на C, хотя это, вероятно, было бы самым быстрым).

Edit:

Просто подчеркнем элегантное решение Aaron, используя match(), который дал увеличение скорости в порядке 1667 раз (от 15 до 0.009)

Я немного расширил его, чтобы разрешить несколько совпадений (возврат - это список)

a <- list(1:3, 3:5, 3:7)
b <- c(3, 5)
g <- rep(seq_along(a), sapply(a, length))
sapply(b, function(x) g[which(unlist(a) %in% x)])
[[1]]
[1] 1 2 3

[[2]]
[1] 2 3

Время выполнения для этого было 0.169, что, возможно, было довольно медленным, но, с другой стороны, более гибким

4b9b3361

Ответ 1

Здесь одна возможность с использованием match:

> a <- list(1:3, 4:5, 6:9)
> b <- c(2, 3, 5, 8)
> g <- rep(seq_along(a), sapply(a, length))
> g[match(b, unlist(a))]
[1] 1 1 2 3

findInterval - это еще один вариант:

> findInterval(match(b, unlist(a)), cumsum(c(0,sapply(a, length)))+1)
[1] 1 1 2 3

Чтобы вернуть список, попробуйте следующее:

a <- list(1:3, 4:5, 5:9)
b <- c(2,3,5,8,5)
g <- rep(seq_along(a), sapply(a, length))
aa <- unlist(a)
au <- unique(aa)
af <- factor(aa, levels=au)
gg <- split(g, af)
gg[match(b, au)]

Ответ 2

Как следует из комментария к вашему сообщению, это зависит от того, что вы хотите сделать, если/когда один и тот же элемент появляется в нескольких векторах в a. Предполагая, что вам нужен самый низкий индекс, который вы могли бы сделать:

apply(sapply(a, function(vec) {b %in% vec}), 1, which.max)