2014-10-31 4 views
1

Название не делает этого вопроса справедливым, но я не мог придумать другого способа формулировать вопрос. Я могу лучше всего объяснить проблему на примере.Соответствующие номера по их порядку, когда в двух разных векторах

Допустим, у нас есть два вектора чисел (каждое из которых всегда будет возноситься и уникальным):

vector1 <- c(1,3,10,11,24,26,30,31) 
vector2 <- c(5,9,15,19,21,23,28,35) 

То, что я пытаюсь сделать, это создать функцию, которая будет принимать эти два вектора и сопоставить их следующим образом:

1) Начните с первым элементом Vector1 (в данном случае 1)

2) Перейти к Vector2 и соответствует элементу из # 1 с первым элементом в векторе- что больше его (в данном случае 5)

3) Вернитесь к Vector1 и пропустить все элементы меньше, чем значение в # 2 мы нашли (в данном случае, мы пропускаем 3, и захватить 10)

4) Вернитесь к Vector2 и пропустить все элементы меньше, чем значение в № 3, которое мы нашли (в этом случае мы пропускаем 9 и захватываем 15)

5) повторяем, пока мы не закончим со всеми элементами.

Полученные в результате двух векторов мы должны иметь являются:

result1 = c(1,10,24,30) 
result2 = c(5,15,28,35) 

Мое текущее решение идет что-то вроде этого, но я считаю, что это может быть крайне неэффективно:

# establishes where we start from the vector2 numbers 
# just in case we have vector1 <- c(5,8,10) 
# and vector2 <- c(1,2,3,4,6,7). We would want to skip the 1,2,3,4 values 

    i <- 1 
    while(vector2[i]<vector1[1]){ 
    i <- i+1 
    } 

# starts the result1 vector with the first value from the vector1 

    result1 <- vector1[1] 

# starts the result2 vector empty and will add as we loop through 

    result2 <- c() 


# super complicated and probably hugely inefficient loop within a loop within a loop 
# i really want to avoid doing this, but I cannot think of any other way to accomplish this 

    for(j in 1:length(vector1)){ 

    while(vector1[j] > vector2[i] && (i+1) <= length(vector2)){ 

     result1 <- c(result1,vector1[j]) 
     result2 <- c(result2,vector2[i])   

     while(vector1[j] > vector2[i+1] && (i+2) <= length(vector2)){ 

     i <- i+1 
     } 
     i <- i+1 
    } 
    } 

    ## have to add on the last vector2 value cause while loop skips it 
    ## if it doesn't exist (there are no more vector2 values bigger) we put in an NA 

    if(result1[length(result1)] < vector2[i]){ 
    result2 <- c(result2,vector2[i]) 
    } 
    else{ 
    ### we ran out of vector2 values that are bigger 
    result2 <- c(result2,NA) 
    } 

ответ

2

Это действительно трудно объяснить , Просто назвать это волшебство :)

vector1 <- c(1,3,10,11,24,26,30,31) 
vector2 <- c(5,9,15,19,21,23,28,35) 
## another case 
# vector2 <- c(0,9,15,19,21,23,28,35) 

## handling the case where vector2 min value(s) are < vector1 min value 
if (any(idx <- which(min(vector1) >= vector2))) 
    vector2 <- vector2[-idx] 

## interleave the two vectors 
tmp <- c(vector1,vector2)[order(c(order(vector1), order(vector2)))] 

## if we sort the vectors, which pairwise elements are from the same vector 
r <- rle(sort(tmp) %in% vector1)$lengths 

## I want to "remove" all the pairwise elements which are from the same vector 
## so I again interleave two vectors: 
## the first will be all TRUEs because I want the first instance of each *new* vector 
## the second will be all FALSEs identifying the elements I want to throw out because 
## there is a sequence of elements from the same vector 
l <- rep(1, length(r)) 
ord <- c(l, r - 1)[order(c(order(r), order(l)))] 

## create some dummy TRUE/FALSE to identify the ones I want 
res <- sort(tmp)[unlist(Map(rep, c(TRUE, FALSE), ord))] 

setNames(split(res, res %in% vector2), c('result1', 'result2')) 

# $result1 
# [1] 1 10 24 30 
# 
# $result2 
# [1] 5 15 28 35 

, очевидно, это будет работать только тогда, когда оба вектора восходящие и уникальные, которые вы сказали

EDIT:

работы с дубликатами:

vector1 <- c(1,3,10,11,24,26,30,31) 
vector2 <- c(5,9,15,19,21,23,28,35) 
vector2 <- c(0,9,15,19,21,23,28,35) 
vector2 <- c(1,3,3,5,7,9,28,35) 

f <- function(v1, v2) { 
    if (any(idx <- which(min(vector1) >= vector2))) 
    vector2 <- vector2[-idx] 

    vector1 <- paste0(vector1, '.0') 
    vector2 <- paste0(vector2, '.00') 

    n <- function(x) as.numeric(x) 

    tmp <- c(vector1, vector2)[order(n(c(vector1, vector2)))] 

    m <- tmp[1] 
    idx <- c(TRUE, sapply(1:(length(tmp) - 1), function(x) { 
    if (n(tmp[x + 1]) > n(m)) { 
     if (gsub('^.*\\.','', tmp[x + 1]) == gsub('^.*\\.','', m)) 
     FALSE 
     else { 
     m <<- tmp[x + 1] 
     TRUE 
     } 
    } else FALSE 
    })) 

    setNames(split(n(tmp[idx]), grepl('\\.00$', tmp[idx])), c('result1','result2')) 
} 
f(vector1, vector2) 

# $result1 
# [1] 1 10 30 
# 
# $result2 
# [1] 3 28 35 
+0

что такое умное решение. Я никогда не думал о чередовании двух векторов (я полагаю, я не сделал все возможное из моих предположений о восходящей и уникальности). Я только что изменил последнюю строку кода и заставил ее работать. Спасибо огромное! –

+0

жаль беспокоить, но я заметил ошибку при попытке сравнить ее с моим предыдущим решением. Если значения vector1 начинают превышать значения vector2, выход неверен. Например, vector1 = (3,10, ...) и vector2 являются (1,5,9 ...) Я исправил это, просто изменив vector2, чтобы удалить любые значения, которые ниже начального значения vector1 –

+0

can вы просто используете vector2 как вектор 1 и наоборот? то есть всегда использовать сначала вектор с наименьшим первым элементом? – rawr

Смежные вопросы