如何从字符列表中生成随机单词?
How to generate random words from a list of characters?
我想从字母 "a b c d"
中生成一个包含 50 个单词的列表。每个单词应该有 5 个字符。使用基数 R,每个单词必须在至少 2 个位置(字母)与其他单词不同。
x="a,b,c,d"
结果应该是 50 个单词的列表:
l=['abcda','cdabd','bdaca'.......]
expand.grid R 中的函数生成只有 1 个字母差异的单词。
首先我们需要创建一个助手来测试两个单词是否至少有两个不同的位置(字母):
two_char_distinct <- function(word_1, word_2) {
sum( ! unlist(strsplit(word_1, "")) == unlist(strsplit(word_2, ""))) > 1
}
编辑:最好使用 adist
请参阅@ThomasCoding 回答
然后你用 sample()
生成一个词并将其添加到向量 words
只有当它与所有其他词不同 (two_char_distinct
) 时:
words <- c()
while(length(words) < 50) {
new_word <- paste0(sample(letters[1:4], size = 5, replace = T),
collapse = "")
tests <- sapply(words, function(w) two_char_distinct(w, new_word))
if(all(tests)) words <- c(words, new_word)
}
words
输出
[1] "cdbdc" "bdacc" "cdaad" "dbcca" "baaac" "bdadd" "cbbbd" "dcccb" "ddcad"
[10] "dabdd" "dcacc" "cabdb" "dcada" "ddbba" "acbdc" "cddda" "badbd" "bcbad"
[19] "ccdcb" "addbc" "dcddc" "bcbcc" "dacaa" "ccdba" "badda" "abaca" "adcca"
[28] "bacdc" "dacbd" "bbdcd" "bbcdb" "adbcd" "bcbdb" "cbadb" "caadc" "cbabc"
[37] "bccbc" "bdcda" "dddab" "cdcac" "cbbaa" "bbbba" "ccaab" "adbda" "bddaa"
[46] "aaabd" "abcbc" "cadcd" "aaaaa" "baacb"
如果想从一个完整的单词集合中采样,可以先构建这样一个完整的集合作为第一步(见下面代码中的X
),然后就可以通过 运行 sample(X, 50)
简单地
多次重复使用
v <- do.call(paste0, expand.grid(rep(list(letters[1:4]), 5)))
X <- Reduce(
function(S, k) {
if (all(adist(k, S) >= 2)) {
S <- c(S, k)
}
S
}, v
)
res <- sample(X, 50)
另一种选择是使用 while
循环并在每次迭代中更新所选单词集
res <- paste0(sample(letters[1:4], 5, replace = TRUE), collapse = "")
while (length(res) < 50) {
k <- paste0(sample(letters[1:4], 5, replace = TRUE), collapse = "")
if (all(adist(k, res) >= 2)) {
res <- c(res, k)
}
}
res
我想从字母 "a b c d"
中生成一个包含 50 个单词的列表。每个单词应该有 5 个字符。使用基数 R,每个单词必须在至少 2 个位置(字母)与其他单词不同。
x="a,b,c,d"
结果应该是 50 个单词的列表:
l=['abcda','cdabd','bdaca'.......]
expand.grid R 中的函数生成只有 1 个字母差异的单词。
首先我们需要创建一个助手来测试两个单词是否至少有两个不同的位置(字母):
two_char_distinct <- function(word_1, word_2) {
sum( ! unlist(strsplit(word_1, "")) == unlist(strsplit(word_2, ""))) > 1
}
编辑:最好使用 adist
请参阅@ThomasCoding 回答
然后你用 sample()
生成一个词并将其添加到向量 words
只有当它与所有其他词不同 (two_char_distinct
) 时:
words <- c()
while(length(words) < 50) {
new_word <- paste0(sample(letters[1:4], size = 5, replace = T),
collapse = "")
tests <- sapply(words, function(w) two_char_distinct(w, new_word))
if(all(tests)) words <- c(words, new_word)
}
words
输出
[1] "cdbdc" "bdacc" "cdaad" "dbcca" "baaac" "bdadd" "cbbbd" "dcccb" "ddcad"
[10] "dabdd" "dcacc" "cabdb" "dcada" "ddbba" "acbdc" "cddda" "badbd" "bcbad"
[19] "ccdcb" "addbc" "dcddc" "bcbcc" "dacaa" "ccdba" "badda" "abaca" "adcca"
[28] "bacdc" "dacbd" "bbdcd" "bbcdb" "adbcd" "bcbdb" "cbadb" "caadc" "cbabc"
[37] "bccbc" "bdcda" "dddab" "cdcac" "cbbaa" "bbbba" "ccaab" "adbda" "bddaa"
[46] "aaabd" "abcbc" "cadcd" "aaaaa" "baacb"
如果想从一个完整的单词集合中采样,可以先构建这样一个完整的集合作为第一步(见下面代码中的X
),然后就可以通过 运行 sample(X, 50)
简单地
v <- do.call(paste0, expand.grid(rep(list(letters[1:4]), 5)))
X <- Reduce(
function(S, k) {
if (all(adist(k, S) >= 2)) {
S <- c(S, k)
}
S
}, v
)
res <- sample(X, 50)
另一种选择是使用 while
循环并在每次迭代中更新所选单词集
res <- paste0(sample(letters[1:4], 5, replace = TRUE), collapse = "")
while (length(res) < 50) {
k <- paste0(sample(letters[1:4], 5, replace = TRUE), collapse = "")
if (all(adist(k, res) >= 2)) {
res <- c(res, k)
}
}
res