RosettaCodeData/Task/Natural-sorting/Jq/natural-sorting-1.jq
2023-07-01 13:44:08 -04:00

58 lines
2.3 KiB
Text
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

def splitup:
def tidy: if .[0] == "" then .[1:] else . end | if .[length-1] == "" then .[0:length-1] else . end ;
# a and b are assumed to be arrays:
def alternate(a;b):
reduce range(0; [a,b] | map(length) | max) as $i ([]; . + [a[$i], b[$i]]);
([splits("[0-9]+")] | tidy) as $a
| ([splits("[^0-9]+")] | tidy | map(tonumber)) as $n
| (test("^[0-9]")) as $nfirst
| if $nfirst then alternate($n; $a) else alternate($a; $n) end ;
# The following implementation of tr is more general than needed here, but the generality
# makes for adaptability.
# x and y should both be strings defining a character-by-character translation, like Unix/Linux "tr".
# if y is shorter than x, then y will in effect be padded with y's last character.
# The input may be a string or an exploded string (i.e. an array);
# the output will have the same type as the input.
def tr(x;y):
type as $type
| (x | explode) as $xe
| (y | explode) as $ye
| $ye[-1] as $last
| if $type == "string" then explode else . end
| map( . as $n | ($xe|index($n)) as $i | if $i then $ye[$i]//$last else . end)
| if $type == "string" then implode else . end;
# NOTE: the order in which the filters are applied is consequential!
def natural_sort:
def naturally:
gsub("\\p{M}"; "") # combining characters (accents, umlauts, enclosures, etc)
| tr("ÀÁÂÃÄÅàáâãäåÇçÈÉÊËèéêëÌÍÎÏìíîïÒÓÔÕÖØòóôõöøÑñÙÚÛÜùúûüÝÿý";
"AAAAAAaaaaaaCcEEEEeeeeIIIIiiiiOOOOOOooooooNnUUUUuuuuYyy")
# Ligatures:
| gsub("Æ"; "AE")
| gsub("æ"; "ae")
| gsub("\u0132"; "IJ") # IJ
| gsub("\u0133"; "ij") # ij
| gsub("\u0152"; "Oe") # Œ
| gsub("\u0153"; "oe") # œ
| gsub("ffl"; "ffl")
| gsub("ffi"; "ffi")
| gsub("fi" ; "fi")
| gsub("ff" ; "ff")
| gsub("fl" ; "fl")
# Illustrative replacements:
| gsub("ß" ; "ss") # German scharfes S
| gsub("ſ|ʒ"; "s") # LATIN SMALL LETTER LONG S and LATIN SMALL LETTER EZH
| ascii_downcase
| gsub("\\p{Cc}+";" ") # control characters
| gsub("^(the|a|an) "; "") # leading the/a/an (as words)
| gsub("\\s+"; " ") # whitespace
| sub("^ *";"") # leading whitespace
| sub(" *$";"") # trailing whitespace
| splitup # embedded integers
;
sort_by(naturally);