Как уже упоминалось в комментариях, использование table()
на длинах rle()
, вероятно, является наиболее кратким решением
Например:
x <- c(3, 1, 1, 3, 4, 5, 3, 1, 5, 4, 2, 4, 2, 3, 2, 3, 2, 4, 5, 4)
table(rle(x)$lengths)
# 1 2
# 18 1
# or
v <- c(1, 1, 2, 4, 5, 5, 4, 5, 5, 3, 3, 2, 2, 2, 1, 4, 4, 4, 2, 1)
table(rle(v)$lengths)
# 1 2 3
# 6 4 2
В первом примере 18 синглов иодин двойной (два 1
в начале), всего 1*18 + 2*1 = 20
значений
Во втором примере 6 синглов, 4 двойных и 2 тройки, что в сумме составляет 1*6 + 2*4 + 3*2 = 20
values
Но если скорость вычислений важнее, чем сжатый код, мы можем добиться большего успеха, так как table()
и rle()
выполняют вычисления внутри себя, которые нам на самом деле не нужны.Вместо этого мы можем собрать функцию, которая выполняет только минимум.
runlengths <- function(x) {
n <- length(x)
r <- which(x[-1] != x[-n])
rl <- diff(c(0, r, n))
rlu <- sort(unique(rl))
rlt <- tabulate(match(rl, rlu))
names(rlt) <- rlu
as.table(rlt)
}
runlengths(x)
# 1 2
# 18 1
runlengths(v)
# 1 2 3
# 6 4 2
Бонус:
Вы уже знаете, что можете сравнивать отдельные элементы вектора, как этот
x[1] == x[2]
x[2] == x[3]
но знаете ли вы, что вы можете сравнивать векторы друг с другом и что вы можете выбрать несколько элементов из вектора, указав несколько индексов?Вместе это означает, что мы можем вместо того, чтобы делать
x[1] == x[2]
x[2] == x[3]
.
.
.
x[18] == x[19]
x[19] == x[20]
do
x[1:19] == x[2:20]
# Or even
x[-length(x)] == x[-1]