#r #string #loops
Вопрос:
Я хотел бы вставить/свернуть элементы вектора вместе на основе индекса, по которому сначала появляется строка, до тех пор, пока она не появится снова. Например,
v lt;- c("foo", "bar1", "bar2", "foo", "bar1", "foo", "bar1", "bar2", "bar3", "foo") v [1] "foo" "bar1" "bar2" "foo" "bar1" "foo" "bar1" "bar2" "bar3" "foo"
Я могу сделать это с помощью
c(paste0(v[1:3], collapse = ""), paste0(v[4:5], collapse = ""), paste0(v[6:9], collapse = ""), paste0(v[10:10], collapse = "")) [1] "foobar1bar2" "foobar1" "foobar1bar2bar3" "foo"
Шаблон всегда «foo», но количество элементов после foo всегда меняется (например, в этом примере это 2, 1, 3, 0). Существует большое количество строк, поэтому я бы предпочел избежать цикла. Я думаю, что мог бы использовать
b lt;- which(v == "foo") b [1] 1 4 6 10 sapply(1:(length(b)-1), function(x) paste0(v[b[x]:(b[x 1]-1)], collapse = "")) [1] "foobar1bar2" "foobar1" "foobar1bar2bar3"
Я скучаю по последнему «фу». Любая помощь будет очень признательна!
Ответ №1:
как насчет этого
sapply(split(v, cumsum(v=='foo')), paste0, collapse='')
Комментарии:
1. Это до смешного просто! Отличный ответ.
2. Это очень чисто, спасибо!
Ответ №2:
Я думаю, тебе просто нужно справиться с этим последним «фу».:
v lt;- c("foo", "bar1", "bar2", "foo", "bar1", "foo", "bar1", "bar2", "bar3", "foo") b lt;- which(v == "foo") sapply(seq_along(b), function(i) { if (i lt; length(b)) { paste(v[b[i]:(b[i 1] - 1)], collapse = "") } else { v[b[i]] } } )
Это возвращает
#gt; [1] "foobar1bar2" "foobar1" "foobar1bar2bar3" "foo"