【发布时间】:2021-05-02 13:33:23
【问题描述】:
给定
author = c("A","B","A","B","C","D","C")
我希望输出是以下任何一种:
[1] 1 2 2 2 3 4 2
或者
[1] 1 2 1 2 3 4 1
或者
[1] 2 4 1
第一个给出唯一字母的滚动数,第二个是一个计数器,每当一个字母重复时重置为 1,最后一个计算唯一运行的长度(即 A-B 是 2,@987654327 @ 是 4,B 是 1)。
第一个实现是最好的,因为它永远不会错过一个连胜。
目前我有第三个实现:
author = c("A","B","A","B","C","D","C")
n = length(author)
streak = rep(0,floor(n/2))
i = 1; counter = 1
while (i <= n)
{
p = duplicated(author[i:(i+35)])
i_new = i + Position(function(x) x==TRUE, p) - 1
streak[counter] = i_new - i
i = i_new
counter = counter + 1
}
streak
这会计算非重复项的数量,直到第一个重复项,并将索引位置更改为中断非重复项连续运行的元素。我确定这比跟踪我看到的元素并检查每个新元素是否重复要快。
它的输出是2 4 0(因为i+35 超出了给定author 的范围),这没关系,因为最后一个元素并不那么重要。我们也可以假设没有超过 35 的连续。
我的主要问题是这需要很长时间才能运行,因为真正的 author 向量很大。
我怎样才能更有效地执行这项任务?
编辑:按照@Dikran 的回答,更新后的代码是:
author = c("A","B","A","B","C","D","C")
authorList = unique(author)
authorVals = 1:length(authorList)
authorHash = setNames(authorVals, authorList) # in R internally is a hash table
authorTabl = rep(0, length(authorVals))
author = as.integer(revalue(author, authorHash))
n = length(author)
streak = rep(0,floor(n/2))
index = rep(0,floor(n/2))
i = 1; counter = 1; first = 1; last = 1
for (i in 1:n)
{
authorTabl[author[last]] = authorTabl[author[last]] + 1
while (authorTabl[author[last]] == 2)
{
authorTabl[author[first]] = authorTabl[author[first]] - 1
first = first + 1
}
last = last + 1
streak[counter] = last - first
counter = counter + 1
}
streak
速度很快,而且:
[1] 1 2 2 2 3 4 2
【问题讨论】:
-
作者集中有多少个不同的值?
-
@DikranMarsupial 有 4,000 位独立作者,但其中 40 位占该集合的 95%。总共有 2200 万个条目。