Jak mogę skutecznie sortować znaki każdego łańcucha w wektorze? Na przykład, biorąc pod uwagę wektor ciągów:
set.seed(1)
strings <- c(do.call(paste0, replicate(4, sample(LETTERS, 10000, TRUE), FALSE)),
do.call(paste0, replicate(3, sample(LETTERS, 10000, TRUE), FALSE)),
do.call(paste0, replicate(2, sample(LETTERS, 10000, TRUE), FALSE)))
Napisałem funkcję, która podzieli każdy ciąg na wektor, posortuje wektor, a następnie zwinie dane wyjściowe:
sort_cat <- function(strings){
tmp <- strsplit(strings, split="")
tmp <- lapply(tmp, sort)
tmp <- lapply(tmp, paste0, collapse = "")
tmp <- unlist(tmp)
return(tmp)
}
sorted_strings <- sort_cat(strings)
Jednak wektor ciągów, do którego muszę to zastosować, jest bardzo długi, a ta funkcja jest zbyt wolna. Czy ktoś ma jakieś sugestie dotyczące poprawy wydajności?
r
string
performance
sorting
Powege
źródło
źródło
letters
Nie zawsze są trzy długości jak w przykładzie, są?fixed = TRUE
wstrsplit()
może poprawić wydajność, ponieważ nie będzie wiązać się z użyciem regex.Odpowiedzi:
Możesz skrócić czas, minimalizując na pewno liczbę pętli, a następnie zrób to, używając
parallel
pakietu ... moim podejściem byłoby podzielenie ciągów raz, a następnie w sortowaniu i wklejaniu pętli:Goli się jak 4 sekundy, ale wciąż nie jest tak szybko ...
Edytować
Dobra, udało mi się to osiągnąć, używając
apply
strategii tutaj:1) wyodrębniaj litery zamiast dzielonych granic 2) utwórz matrycę z wynikami 3) iteruj po wierszach 4) Sortuj 5) Dołącz
Unikasz wielu pętli i niepublicznych… IGNORE:? Zastrzeżeniem
jest, jeśli ciągi o różnych długościach, musisz usunąć wszelkie puste lub NA wapply
takich jaki[!is.na(i) && nchar(i) > 0]
Zajmuje nam od 10,3 sekundy do 3,98
źródło
tmp <- strsplit(strings, split="") unlist(mclapply(tmp, function(i){ paste0(sort(i), collapse = "") }))
stringi
to moja ulubiona paczka jak dotąd ...Ponowne wdrożenie za pomocą
stringi
daje około 4x przyspieszenie. Zredagowałem również,sort_cat
aby użyćfixed = TRUE
wstrsplit
, co sprawia, że jest trochę szybszy. I dzięki Carlowi za sugestię pojedynczej pętli, która przyspiesza nas jeszcze trochę.Metodę tę można również stosować równolegle. Profilowanie kodu, aby zobaczyć, które operacje faktycznie trwają najdłużej, byłoby dobrym następnym krokiem, jeśli chcesz iść jeszcze szybciej.
źródło
Ta wersja jest nieco szybsza
Ale myślę, że można to zoptymalizować
źródło