如何在多个数组中找到连续的数字?
How to find Consecutive Numbers Among multiple Arrays?
我马上举个例子,
现在假设我有 3 个数组 a、b、c,例如
a = c(3,5)
b = c(6,1,8,7)
c = c(4,2,9)
我必须能够提取其中的连续三元组,即
c(1,2,3),c(4,5,6)
但这只是一个例子,我会有一个更大的数据集,甚至超过 10 个数组,因此必须能够找到长度为 10 的连续序列。
所以谁能提供一种算法,在 'n' 个数组中找到长度为 'n' 的连续序列。
我实际上是在 R 中做这些事情,所以如果您在 R 中提供代码会更好。然而,来自任何语言的算法都非常受欢迎。
这是一种方法。这假设在组数的观察序列中没有中断。这里是数据。
N <- 3
a <- c(3,5)
b <- c(6,1,8,7)
c <- c(4,2,9)
然后我将它们组合在一起并根据观察结果排序
dd <- lattice::make.groups(a,b,c)
dd <- dd[order(dd$data),]
现在我在这个 table 中查找代表所有三个组的行
idx <- apply(embed(as.numeric(dd$which),N), 1, function(x) {
length(unique(x))==N
})
然后我们可以看到三胞胎
lapply(which(idx), function(i) {
dd[i:(i+N-1),]
})
# [[1]]
# data which
# b2 1 b
# c2 2 c
# a1 3 a
#
# [[2]]
# data which
# c1 4 c
# a2 5 a
# b1 6 b
这是一个蛮力方法expand.grid
和示例中的三个向量
# get all combinations
df <- expand.grid(a,b,c)
使用combn
计算每对组合的差异。
# get all parwise differences
myDiffs <- combn(names(df), 2, FUN=function(x) abs(x[1]-x[2]))
# subset data using `rowSums` and `which`
df[which(rowSums(myDiffs == 1) == ncol(myDiffs)-1), ]
df[which(rowSums(myDiffs == 1) == ncol(myDiffs)-1), ]
Var1 Var2 Var3
2 5 6 4
11 3 1 2
首先将数据重组为包含值和数组编号的列表。
对列表进行排序;你会有这样的东西:
1-2
2-3
3-1 (i.e. " there' s a three in array 1" )
4-3
5-1
6-2
7-2
8-2
9-3
然后循环列表,检查是否真的有n个连续的数字,然后检查它们是否有不同的数组编号
我编写了一个小的递归函数,它会在您传递给它的尽可能多的向量中找到所有连续的三元组(至少需要传递三个)。它可能有点粗糙,但似乎有效。
该函数使用省略号 ...
来传递参数。因此,无论您提供多少参数(即数字向量),它都会将它们放入列表 items
中。然后找到每个传递的向量中的最小值及其索引。
然后创建对应于最小三元组的向量的索引,并使用 for()
循环进行迭代,其中输出值传递给输出向量 out
。 items
中的输入向量被修剪并以递归方式再次传递到函数中。
只是,当所有的向量都是NA
,即向量中没有更多的值时,函数return就是最终的结果。
library(magrittr)
# define function to find the triplets
tripl <- function(...){
items <- list(...)
# find the smallest number in each passed vector, along with its index
# output is a matrix of n-by-2, where n is the number of passed arguments
triplet.id <- lapply(items, function(x){
if(is.na(x) %>% prod) id <- c(NA, NA)
else id <- c(which(x == min(x)), x[which(x == min(x))])
}) %>% unlist %>% matrix(., ncol=2, byrow=T)
# find the smallest triplet from the passed vectors
index <- order(triplet.id[,2])[1:3]
# create empty vector for output
out <- vector()
# go through the smallest triplet's indices
for(i in index){
# .. append the coresponding item from the input vector to the out vector
# .. and remove the value from the input vector
if(length(items[[i]]) == 1) {
out <- append(out, items[[i]])
# .. if the input vector has no value left fill with NA
items[[i]] <- NA
}
else {
out <- append(out, items[[i]][triplet.id[i,1]])
items[[i]] <- items[[i]][-triplet.id[i,1]]
}
}
# recurse until all vectors are empty (NA)
if(!prod(unlist(is.na(items)))) out <- append(list(out),
do.call("tripl", c(items), quote = F))
else(out <- list(out))
# return result
return(out)
}
可以通过将输入向量作为参数传递来调用该函数。
# input vectors
a = c(3,5)
b = c(6,1,8,7)
c = c(4,2,9)
# find all the triplets using our function
y <- tripl(a,b,c)
结果是一个列表,其中包含所有必要的信息,尽管是无序的。
print(y)
# [[1]]
# [1] 1 2 3
#
# [[2]]
# [1] 4 5 6
#
# [[3]]
# [1] 7 9 NA
#
# [[4]]
# [1] 8 NA NA
订购一切都可以使用 sapply()
:
# put everything in order
sapply(y, function(x){x[order(x)]}) %>% t
# [,1] [,2] [,3]
# [1,] 1 2 3
# [2,] 4 5 6
# [3,] 7 9 NA
# [4,] 8 NA NA
事实是,它将仅使用每个向量的一个值来查找三元组。
因此,它不会在例如中找到连续的三元组 c(6,7,8)
。 c(6,7,11)
、c(8,9,13)
和 c(10,12,14)
。
在这种情况下,它将 return c(6,8,10)
(见下文)。
a<-c(6,7,11)
b<-c(8,9,13)
c<-c(10,12,14)
y <- tripl(a,b,c)
sapply(y, function(x){x[order(x)]}) %>% t
# [,1] [,2] [,3]
# [1,] 6 8 10
# [2,] 7 9 12
# [3,] 11 13 14
我马上举个例子, 现在假设我有 3 个数组 a、b、c,例如
a = c(3,5)
b = c(6,1,8,7)
c = c(4,2,9)
我必须能够提取其中的连续三元组,即
c(1,2,3),c(4,5,6)
但这只是一个例子,我会有一个更大的数据集,甚至超过 10 个数组,因此必须能够找到长度为 10 的连续序列。
所以谁能提供一种算法,在 'n' 个数组中找到长度为 'n' 的连续序列。
我实际上是在 R 中做这些事情,所以如果您在 R 中提供代码会更好。然而,来自任何语言的算法都非常受欢迎。
这是一种方法。这假设在组数的观察序列中没有中断。这里是数据。
N <- 3
a <- c(3,5)
b <- c(6,1,8,7)
c <- c(4,2,9)
然后我将它们组合在一起并根据观察结果排序
dd <- lattice::make.groups(a,b,c)
dd <- dd[order(dd$data),]
现在我在这个 table 中查找代表所有三个组的行
idx <- apply(embed(as.numeric(dd$which),N), 1, function(x) {
length(unique(x))==N
})
然后我们可以看到三胞胎
lapply(which(idx), function(i) {
dd[i:(i+N-1),]
})
# [[1]]
# data which
# b2 1 b
# c2 2 c
# a1 3 a
#
# [[2]]
# data which
# c1 4 c
# a2 5 a
# b1 6 b
这是一个蛮力方法expand.grid
和示例中的三个向量
# get all combinations
df <- expand.grid(a,b,c)
使用combn
计算每对组合的差异。
# get all parwise differences
myDiffs <- combn(names(df), 2, FUN=function(x) abs(x[1]-x[2]))
# subset data using `rowSums` and `which`
df[which(rowSums(myDiffs == 1) == ncol(myDiffs)-1), ]
df[which(rowSums(myDiffs == 1) == ncol(myDiffs)-1), ]
Var1 Var2 Var3
2 5 6 4
11 3 1 2
首先将数据重组为包含值和数组编号的列表。 对列表进行排序;你会有这样的东西:
1-2
2-3
3-1 (i.e. " there' s a three in array 1" )
4-3
5-1
6-2
7-2
8-2
9-3
然后循环列表,检查是否真的有n个连续的数字,然后检查它们是否有不同的数组编号
我编写了一个小的递归函数,它会在您传递给它的尽可能多的向量中找到所有连续的三元组(至少需要传递三个)。它可能有点粗糙,但似乎有效。
该函数使用省略号 ...
来传递参数。因此,无论您提供多少参数(即数字向量),它都会将它们放入列表 items
中。然后找到每个传递的向量中的最小值及其索引。
然后创建对应于最小三元组的向量的索引,并使用 for()
循环进行迭代,其中输出值传递给输出向量 out
。 items
中的输入向量被修剪并以递归方式再次传递到函数中。
只是,当所有的向量都是NA
,即向量中没有更多的值时,函数return就是最终的结果。
library(magrittr)
# define function to find the triplets
tripl <- function(...){
items <- list(...)
# find the smallest number in each passed vector, along with its index
# output is a matrix of n-by-2, where n is the number of passed arguments
triplet.id <- lapply(items, function(x){
if(is.na(x) %>% prod) id <- c(NA, NA)
else id <- c(which(x == min(x)), x[which(x == min(x))])
}) %>% unlist %>% matrix(., ncol=2, byrow=T)
# find the smallest triplet from the passed vectors
index <- order(triplet.id[,2])[1:3]
# create empty vector for output
out <- vector()
# go through the smallest triplet's indices
for(i in index){
# .. append the coresponding item from the input vector to the out vector
# .. and remove the value from the input vector
if(length(items[[i]]) == 1) {
out <- append(out, items[[i]])
# .. if the input vector has no value left fill with NA
items[[i]] <- NA
}
else {
out <- append(out, items[[i]][triplet.id[i,1]])
items[[i]] <- items[[i]][-triplet.id[i,1]]
}
}
# recurse until all vectors are empty (NA)
if(!prod(unlist(is.na(items)))) out <- append(list(out),
do.call("tripl", c(items), quote = F))
else(out <- list(out))
# return result
return(out)
}
可以通过将输入向量作为参数传递来调用该函数。
# input vectors
a = c(3,5)
b = c(6,1,8,7)
c = c(4,2,9)
# find all the triplets using our function
y <- tripl(a,b,c)
结果是一个列表,其中包含所有必要的信息,尽管是无序的。
print(y)
# [[1]]
# [1] 1 2 3
#
# [[2]]
# [1] 4 5 6
#
# [[3]]
# [1] 7 9 NA
#
# [[4]]
# [1] 8 NA NA
订购一切都可以使用 sapply()
:
# put everything in order
sapply(y, function(x){x[order(x)]}) %>% t
# [,1] [,2] [,3]
# [1,] 1 2 3
# [2,] 4 5 6
# [3,] 7 9 NA
# [4,] 8 NA NA
事实是,它将仅使用每个向量的一个值来查找三元组。
因此,它不会在例如中找到连续的三元组 c(6,7,8)
。 c(6,7,11)
、c(8,9,13)
和 c(10,12,14)
。
在这种情况下,它将 return c(6,8,10)
(见下文)。
a<-c(6,7,11)
b<-c(8,9,13)
c<-c(10,12,14)
y <- tripl(a,b,c)
sapply(y, function(x){x[order(x)]}) %>% t
# [,1] [,2] [,3]
# [1,] 6 8 10
# [2,] 7 9 12
# [3,] 11 13 14