Дароциг пишет: «Вы можете написать много аккуратного кода на основе diff
» ...
Вот один из способов:
split(v, cumsum(diff(c(-Inf, v)) != 1))
РЕДАКТИРОВАТЬ (добавлено время):
Томми обнаружил, что это может быть быстрее, если быть осторожным с типами; причина, по которой он стал быстрее, состоит в том, что split
быстрее на целых числах, и на самом деле быстрее, чем на факторы
Вот решение Иисуса Навина; результат от cumsum
является числовым, потому что он c
'с 1
, поэтому он самый медленный.
system.time({
a <- cumsum(c(1, diff(v) != 1))
split(v, a)
})
# user system elapsed
# 1.839 0.004 1.848
Просто c
с 1L
, так что результат - целое число, значительно ускоряет его.
system.time({
a <- cumsum(c(1L, diff(v) != 1))
split(v, a)
})
# user system elapsed
# 0.744 0.000 0.746
Это решение Томми, для справки; оно также разбивается на целое число.
> system.time({
a <- cumsum(c(TRUE, diff(v) != 1L))
split(v, a)
})
# user system elapsed
# 0.742 0.000 0.746
Вот мое оригинальное решение; оно также разбивается на целое число.
system.time({
a <- cumsum(diff(c(-Inf, v)) != 1)
split(v, a)
})
# user system elapsed
# 0.750 0.000 0.754
Вот Джошуа с результатом, преобразованным в целое число перед split
.
system.time({
a <- cumsum(c(1, diff(v) != 1))
a <- as.integer(a)
split(v, a)
})
# user system elapsed
# 0.736 0.002 0.740
Все версии, которые split
на целочисленном векторе, примерно одинаковы; это могло бы быть даже быстрее, если бы этот целочисленный вектор уже был фактором, поскольку преобразование из целого числа в множитель фактически занимает примерно половину времени. Здесь я превращаю это непосредственно в фактор; это вообще не рекомендуется, потому что это зависит от структуры класса факторов. Это сделано только для сравнения.
system.time({
a <- cumsum(c(1L, diff(v) != 1))
a <- structure(a, class = "factor", levels = 1L:a[length(a)])
split(v,a)
})
# user system elapsed
# 0.356 0.000 0.357