@@ -1526,7 +1526,6 @@ replace_dot_alias = function(e) {
15261526 if (length(byval ) && length(byval [[1L ]])) {
15271527 if (! bysameorder && isFALSE(byindex )) {
15281528 if (verbose ) {last.started.at = proc.time();catf(" Finding groups using forderv ... " );flush.console()}
1529- browser()
15301529 o__ = forderv(byval , sort = keyby , retGrp = TRUE )
15311530 # The sort= argument is called sortGroups at C level. It's primarily for saving the sort of unique strings at
15321531 # C level for efficiency when by= not keyby=. Other types also retain appearance order, but at byte level to
@@ -2013,8 +2012,8 @@ replace_dot_alias = function(e) {
20132012 if (verbose ) {last.started.at = proc.time();catf(" setkey() afterwards for keyby=.EACHI ... " );flush.console()}
20142013 setkeyv(ans ,names(ans )[seq_along(byval )])
20152014 if (verbose ) {cat(timetaken(last.started.at )," \n " ); flush.console()}
2016- } else if (keyby || (haskey( x ) && bysameorder && ( byjoin || (length( allbyvars ) && identical( allbyvars ,head(key( x ),length( allbyvars ))))) )) {
2017- setattr(ans ," sorted" ,names(ans )[seq_along(grpcols )])
2015+ } else if (.by_result_is_keyable( x , keyby , bysameorder , byjoin , allbyvars , bysub )) {
2016+ setattr(ans , " sorted" , names(ans )[seq_along(grpcols )])
20182017 }
20192018 setalloccol(ans ) # TODO: overallocate in dogroups in the first place and remove this line
20202019}
@@ -3042,6 +3041,21 @@ rleidv = function(x, cols=seq_along(x), prefix=NULL) {
30423041 ids
30433042}
30443043
3044+ .by_result_is_keyable = function (x , keyby , bysameorder , byjoin , byvars , bysub ) {
3045+ if (keyby ) return (TRUE )
3046+ k = key(x )
3047+ if (is.null(k )) return (FALSE ) # haskey(x) but saving 'k' for below
3048+ if (! bysameorder ) return (FALSE )
3049+ if (byjoin ) return (TRUE )
3050+ if (! length(byvars )) return (FALSE )
3051+ if (! identical(byvars , head(k , length(byvars )))) return (FALSE ) # match key exactly, in order
3052+ # For #5583, we also ensure there are no function calls in by (which might break sortedness)
3053+ if (is.name(bysub )) return (TRUE )
3054+ if (identical(bysub [[1L ]], quote(list ))) bysub = bysub [- 1L ]
3055+ if (length(all.names(bysub )) > length(byvars )) return (FALSE )
3056+ return (TRUE )
3057+ }
3058+
30453059.is_withFALSE_range = function (e , x , root = root_name(e ), vars = all.vars(e )) {
30463060 if (root != " :" ) return (FALSE )
30473061 if (! length(vars )) return (TRUE ) # e.g. 1:10
0 commit comments