[英]Sorting strings lexicographically based upon certain character order
我正在努力解決 Rosalind 問題,並且陷入了Ordering Strings of Varying Length Lexicographically問題。
到目前為止,我已經成功地創建了不同長度字母的所有正確排列。 現在的主要問題是如何根據字母提供的順序對它們進行排序。
示例輸入是字母DNA
。 但在 n <= 4 個排列中最多可以有 12 個唯一字母。
對於示例 n = 3。這會產生 39 種不同的重復排列,但這些排列隨后將按照D
在N
在A
之前的順序按字典順序排序。
這意味着正確的順序是:
正確的 | 不正確 |
---|---|
丁 | 一種 |
DD | AA |
DDD | AAA級 |
專線專線 | AAD |
DDA | 安聯 |
DN | 廣告 |
免打擾 | 艾達 |
神經網絡 | 添加 |
脫氧核糖核酸 | 自動駕駛網絡 |
達 | 一個 |
爸爸 | 全日空 |
擔 | 和 |
DAA | 人工神經網絡 |
... | ... |
AAD | 新南威爾士州 |
安聯 | NND |
AAA級 | 神經網絡 |
我的第一個想法是將它們轉換為具有水平的因素,然后嘗試根據它們的水平對它們進行排序,但我不能完全做到這一點。
到目前為止,我創建了所有排列的列表,然后嘗試對其進行排序,但不知道如何讓排序遵循給定的DNA
順序
text_input <- c("D", "N", "A")
n <- 3
empty_df <- data.frame(matrix("", ncol = n))
temp_df <- data.frame()
for (i in n:1) {
temp_df <- data.frame(arrangements::permutations(text_input, k = i, replace = TRUE))
empty_df <- bind_rows(empty_df, temp_df)
}
result_df <- replace(empty_df, is.na(empty_df), "") |>
unite(col = combined, everything(), sep = "", remove = FALSE) |>
mutate(across(2:(n+2), ~ factor(.x, levels = text_input)),
across(2:(n+2), ~ str_replace_na(.x, replacement = "")))
result_vec <- tail(result_df$combined, -1)
我將使用您擁有的樣本數據, Correct
的,隨機的,以確保我們得到正確的順序。
quux <- structure(list(Correct = c("D", "DD", "DDD", "DDN", "DDA", "DN", "DND", "DNN", "DNA", "DA", "DAD", "DAN", "DAA", "AAD", "AAN", "AAA"), Incorrect = c("A", "AA", "AAA", "AAD", "AAN", "AD", "ADA", "ADD", "ADN", "AN", "ANA", "AND", "ANN", "NNA", "NND", "NNN")), row.names = c(1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L, 11L, 12L, 13L, 15L, 16L, 17L), class = "data.frame")
set.seed(42)
quuxR <- quux[sample(nrow(quux)),]
quuxR$Correct
# [1] "D" "DDA" "AAA" "DNA" "DA" "DDN" "DD" "AAD" "DNN" "DND" "DAD" "DAA" "AAN" "DAN" "DDD" "DN"
ltrs <- c("D", "N", "A")
inds <- lapply(strsplit(quux$Correct, ""), match, table = ltrs)
inds <- lapply(inds, `length<-`, max(lengths(inds)))
quuxR$Correct[do.call(order, c(do.call(Map, c(f=c, inds)), list(na.last = FALSE)))]
# [1] "D" "DD" "DDD" "DDN" "DDA" "DN" "DND" "DNN" "DNA" "DA" "DAD" "DAN" "DAA" "AAD" "AAN" "AAA"
identical(quux$Correct, quuxR$Correct[do.call(order, c(do.call(Map, c(f=c, inds)), list(na.last = FALSE)))])
# [1] TRUE
腳步:
strsplit(.., "")
將字符串拆分為單個字母。match(.., table=ltrs)
用ltrs
中的索引替換一個字母,這給了我們正確的字母優先級/排序。`length<-`
是因為我們隨后將對它們進行rbind
,但這只有在它們都具有相同的長度時才有效。 執行此步驟(與max(lengths(..))
一起使用NA
填充較短的向量,以便所有子向量具有相同數量的元素。do.call(Map, c(f=c, inds))
將長度為n
的m
個向量列表轉置為長度為n
的列表,每個列表都有m
個元素。 這對下一步非常有幫助......do.call(order, ..)
類似於調用order(L[[1]], L[[2]], L[[3]])
(如果L
是轉置列表),但更具編程性。 我們將list(na.last=FALSE)
作為參數添加到向量列表中,以便我們可以獲得較短字符串的正確排序。您可以使用chartr
並對其結果進行order
,並使用它來對原始無序向量進行子集化。
x <- c("DD", "AAN", "DDD", "DNA", "DAA", "DAD", "DDN", "DDA", "DND",
"DAN", "DNN", "DA", "AAA", "AAD", "DN", "D") #Unordered
y <- c("D", "DD", "DDD", "DDN", "DDA", "DN", "DND", "DNN", "DNA", "DA",
"DAD", "DAN", "DAA", "AAD", "AAN", "AAA") #Target order
z <- x[order(chartr("DNA", "ABC", x))]
identical(z, y)
#[1] TRUE
z
# [1] "D" "DD" "DDD" "DDN" "DDA" "DN" "DND" "DNN" "DNA" "DA" "DAD" "DAN"
#[13] "DAA" "AAD" "AAN" "AAA"
這是另一個解決方案,可能不像其他解決方案那么簡潔。
它以 function 開頭,用數字1
、 2
和3
替換三個字母D
、 N
和A
。
將此 function 應用於無序列表向量並對其應用order
,返回一個有序向量,無序列表可以用它進行切片。
library(tidyverse)
x <- c(
"DD", "AAN", "DDD", "DNA", "DAA", "DAD", "DDN", "DDA", "DND",
"DAN", "DNN", "DA", "AAA", "AAD", "DN", "D"
) # Unordered
er <- function(s) {
s1 <- stringr::str_replace_all(s, "D", "1")
s1 <- stringr::str_replace_all(s1, "N", "2")
s1 <- stringr::str_replace_all(s1, "A", "3")
return(s1)
}
l1 <- order(er(x))
x[l1]
#> [1] "D" "DD" "DDD" "DDN" "DDA" "DN" "DND" "DNN" "DNA" "DA" "DAD" "DAN"
#> [13] "DAA" "AAD" "AAN" "AAA"
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.