Skip to content

Commit 096e827

Browse files
Use _pairs_ of letters to get more stable sorting
1 parent 56ccb2d commit 096e827

1 file changed

Lines changed: 18 additions & 12 deletions

File tree

inst/tests/tests.Rraw

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -233,23 +233,29 @@ ForderObj = function(x, starts=NULL, maxgrpn=NULL, anyna=0L, anyinfnan=0L, anyno
233233
x
234234
}
235235

236-
c_sortable_letters = letters
236+
c_sortable_pairs = apply(expand.grid(letters, letters), 1L, paste, collapse="")
237237
# For some tests of forder() compatibility with base sorting methods.
238-
# Subset the letters until the collation order matches C. This way we don't totally ignore
238+
# Subset the pairs of letters until the collation order matches C. This way we don't totally ignore
239239
# any possible issues with sorting strings in unusual locales (even though this _should_
240240
# be impossible given we _always_ use C-collated order, such a regression test is still
241-
# beneficial as a sanity check).
242-
if (!identical(order(letters, method='shell'), order(letters, method='radix'))) {
241+
# beneficial as a sanity check). Pairs of letters are needed for languages like Latvian which
242+
# have some '<='-like letters e.g. 'i' and 'y' are considered something of a 'tie', except when a
243+
# tie-breaker is needed. For example, 'ya' comes before 'ib' because of 'a' < 'b' and 'i' <= 'y',
244+
# but the letters alone sort as 'i' < 'y'.
245+
if (!identical(order(c_sortable_pairs, method='shell'), order(c_sortable_pairs, method='radix'))) {
243246
repeat {
244-
sorted_c = c_sortable_letters[order(c_sortable_letters, method='radix')]
245-
sorted_r = c_sortable_letters[order(c_sortable_letters, method='shell')]
247+
sorted_c = c_sortable_pairs[order(c_sortable_pairs, method='radix')]
248+
sorted_r = c_sortable_pairs[order(c_sortable_pairs, method='shell')]
246249

247250
mismatch = which(sorted_c != sorted_r)
248251
if (!length(mismatch)) break
249-
c_sortable_letters = c_sortable_letters[-mismatch[1L]]
252+
c_sortable_pairs = c_sortable_pairs[-mismatch[1L]]
250253
}
254+
} else {
255+
# don't pull all 676 pairs, but also not sample() for stability
256+
c_sortable_pairs = c_sortable_pairs[seq(1L, length(c_sortable_pairs), length.out=75L)]
251257
}
252-
if (length(c_sortable_letters) < 5L) {
258+
if (length(c_sortable_pairs) < 5L) {
253259
stop("This locale collates too differently from C; please report.")
254260
}
255261

@@ -4474,12 +4480,12 @@ test(1221, DT[.(1),b], c("a","c","e"))
44744480
seed = as.integer(Sys.time()) # sample(9999L, 1L) temporary fix, because all the set.seed(.) used above makes this sample() step deterministic (always seed=9107)
44754481
# no NaN (because it's hard to match with base::order); tested below in 1988.4-8
44764482
set.seed(seed)
4477-
foo <- function(n) apply(matrix(sample(c_sortable_letters, n*8L, TRUE), ncol=8L), 1, paste, collapse="")
4483+
foo <- function(n) apply(matrix(sample(c_sortable_pairs, n*4L, TRUE), ncol=4L), 1, paste, collapse="")
44784484
i1 = as.integer(sample(c(-100:100), 1e3, TRUE))
44794485
i2 = as.integer(sample(c(-100:100, -1e6, 1e6), 1e3, TRUE))
44804486
d1 = as.numeric(sample(c(-100:100,Inf,-Inf), 1e3, TRUE))
44814487
d2 = as.numeric(rnorm(1e3))
4482-
c1 = sample(c_sortable_letters, 1e3, TRUE)
4488+
c1 = sample(c_sortable_pairs, 1e3, TRUE)
44834489
c2 = sample(foo(50), 1e3, TRUE)
44844490

44854491
DT = data.table(i1, i2, d1, d2, c1, c2)
@@ -4748,11 +4754,11 @@ seed = as.integer(Sys.time())
47484754
# forder consistently to save pull requests failing coverage tests randomly, issue #2346
47494755
set.seed(seed)
47504756
# these variable try to simulate groups of length 1, 2, < 200, > 200 so as to cover all different internal implementations
4751-
foo <- function(n) apply(matrix(sample(c_sortable_letters, n*8L, TRUE), ncol=8L), 1, paste, collapse="")
4757+
foo <- function(n) apply(matrix(sample(c_sortable_pairs, n*4L, TRUE), ncol=4L), 1, paste, collapse="")
47524758
i1 = as.integer(sample(rep(c(-3:3, NA_integer_), c(1, 2, 190, 300, 7, 190, 210, 100))))
47534759
i2 = as.integer(sample(rep(c(-2:2, -1e6, 1e6, NA_integer_), c(1, 2, 190, 300, 7, 190, 210, 100))))
47544760
d1 = as.numeric(sample(rep(c(-2:2,Inf,-Inf, NA_real_, 5, -1e3), c(1, 190, 2, 300, 7, 50, 50, 100, 150, 150))))
4755-
c1 = sample(rep(c(c_sortable_letters[1:5], NA_character_, "z"), c(1, 2, 190, 7, 300, 200, 300)))
4761+
c1 = sample(rep(c(c_sortable_pairs[1:5], NA_character_, "z"), c(1, 2, 190, 7, 300, 200, 300)))
47564762
c2 = sample(c(foo(200), NA_character_), 1e3, TRUE)
47574763

47584764
DT = data.table(i1, i2, d1, c1, c2)

0 commit comments

Comments
 (0)