Data update

This commit is contained in:
Ingy döt Net 2024-10-16 18:07:41 -07:00
parent 81fd053722
commit 52a6ef48dd
10248 changed files with 63654 additions and 6775 deletions

View file

@ -0,0 +1,237 @@
#include <algorithm>
#include <cstdint>
#include <iostream>
#include <regex>
#include <string>
#include <vector>
// Only covers ISO-8859-1 accented characters plus, for consistency, Ÿ
const std::vector<std::string> uc_accents =
{ "ÀÁÂÃÄÅ", "Ç", "ÈÉÊË", "ÌÍÎÏ", "Ñ", "ÒÓÔÕÖØ", "ÙÚÛÜ", "ÝŸ" };
const std::vector<std::string> lc_accents =
{ "àáâãäå", "ç", "èéêë", "ìíîï", "ñ", "òóôõöø", "ùúûü", "ýÿ" };
const std::vector<std::string> uc_unaccents = { "A", "C", "E", "I", "N", "O", "U", "Y" };
const std::vector<std::string> lc_unaccents = { "a", "c", "e", "i", "n", "o", "u", "y" };
// Only the more common ligatures
const std::vector<std::string> uc_ligatures = { "Æ", "IJ", "Œ" };
const std::vector<std::string> lc_ligatures = { "æ", "ij", "œ" };
const std::vector<std::string> uc_separates = { "AE", "IJ", "OE" };
const std::vector<std::string> lc_separates = { "ae", "ij", "oe" };
// Miscellaneous replacements
const std::vector<std::string> misc_letters = { "ß", "ſ", "ʒ" };
const std::vector<std::string> misc_replacements = { "ss", "s", "s" };
// Remove leading spaces
std::string left_trim(const std::string& text) {
const uint64_t start = text.find_first_not_of(" \n\r\t\f\v");
return ( start == std::string::npos ) ? "" : text.substr(start);
}
// Replace multiple spaces with a single space
std::string replace_spaces(std::string text) {
static const std::regex regex_expr("[ ]{2,}");
text = std::regex_replace(text, regex_expr, " ");
return text;
}
// Replace whitespace with a single space
std::string replace_whitespace(std::string text) {
static const std::regex regex_expr("\\s+");
text = std::regex_replace(text, regex_expr, " ");
return text;
}
// Display strings including whitespace as if the latter were literal characters
std::string to_display_string(std::string text) {
const std::vector<std::string> whitespace_1 = { "\t", "\n", "\u000b", "\u000c", "\r" };
const std::vector<std::string> whitespace_2 = { "\\t", "\\n", "\\u000b", "\\u000c", "\\r" };
for ( uint64_t i = 0; i < whitespace_1.size(); ++i ) {
std::regex regex_expr(whitespace_1[i]);
text = std::regex_replace(text, regex_expr, whitespace_2[i]);
}
return text;
}
// Transform the string into lower case
std::string to_lower_case(std::string text) {
std::transform(text.begin(), text.end(), text.begin(),
[](char ch) { return std::tolower(ch); });
return text;
}
// Pad each numeric character with leading zeros to a total length of 20
std::string zero_padding(std::string text) {
const static std::regex digits("-?\\d+");
const std::vector<std::string> matches{
std::sregex_token_iterator{text.begin(), text.end(), digits, 0}, std::sregex_token_iterator{} };
std::vector<uint64_t> indexes = { };
for ( const std::string& match : matches ) {
indexes.emplace_back(text.find(match));
}
uint32_t extra_index = 0;
for ( uint64_t i = 0; i < matches.size(); ++i ) {
uint64_t start_pos = text.find(matches[i], indexes[i] + extra_index);
text = text.substr(0, start_pos) + std::string(20 - matches[i].size(), '0') + text.substr(start_pos);
extra_index += 20 - matches[i].size();
}
return text;
}
std::string remove_title(std::string text) {
return std::regex_replace(text, std::regex("^The\\s+|^An\\s+|^A\\s+"), "");
}
// Replace accented letters with their unaccented equivalent
std::string replace_accents(const std::string& text) {
std::string result = "";
for ( uint64_t i = 0; i < text.length(); ++i ) {
if ( ( text[i] & 0xff ) < 128 ) {
result += text.substr(i, 1);
continue;
}
const uint64_t length = result.length();
const std::string letter = text.substr(i, 2);
for ( uint64_t j = 0; j < uc_accents.size(); ++j ) {
if ( uc_accents[j].find(letter) != std::string::npos ) {
result += uc_unaccents[j];
break;
}
}
if ( length == result.length() ) {
for ( uint64_t j = 0; j < lc_accents.size(); ++j ) {
if ( lc_accents[j].find(letter) != std::string::npos ) {
result += lc_unaccents[j];
break;
}
}
}
}
return result;
}
// Replace ligatures with separated letters
std::string replace_ligatures(std::string text) {
for ( uint64_t i = 0; i < uc_ligatures.size(); ++i ) {
text = std::regex_replace(text, std::regex(uc_ligatures[i]), uc_separates[i]);
}
for ( uint64_t i = 0; i < lc_ligatures.size(); ++i ) {
text = std::regex_replace(text, std::regex(lc_ligatures[i]), lc_separates[i]);
}
return text;
}
// Replace miscellaneous letters with their equivalent replacements
std::string replace_characters(std::string text) {
for ( uint64_t i = 0; i < misc_letters.size(); ++i ) {
text = std::regex_replace(text, std::regex(misc_letters[i]), misc_replacements[i]);
}
return text;
}
int main() {
std::cout << "The 9 string lists, sorted 'naturally':" << "\n";
std::vector<std::string> s1 = {
"ignore leading spaces: 2-2",
" ignore leading spaces: 2-1",
" ignore leading spaces: 2+0",
" ignore leading spaces: 2+1"
};
std::cout << "\n";;
std::sort(s1.begin(), s1.end(),
[](std::string lhs, std::string rhs) { return left_trim(lhs) < left_trim(rhs); });
for ( const std::string& s : s1 ) { std::cout << s << "\n"; }
std::vector<std::string> s2 = {
"ignore m.a.s spaces: 2-2",
"ignore m.a.s spaces: 2-1",
"ignore m.a.s spaces: 2+0",
"ignore m.a.s spaces: 2+1"
};
std::cout << "\n";;
std::sort(s2.begin(), s2.end(),
[](std::string lhs, std::string rhs) { return replace_spaces(lhs) < replace_spaces(rhs); });
for ( const std::string& s : s2 ) { std::cout << s << "\n"; }
std::vector<std::string> s3 = {
"Equiv. spaces: 3-3",
"Equiv.\rspaces: 3-2",
"Equiv.\u000cspaces: 3-1",
"Equiv.\u000bspaces: 3+0",
"Equiv.\nspaces: 3+1",
"Equiv.\tspaces: 3+2"
};
std::cout << "\n";;
std::sort(s3.begin(), s3.end(),
[](std::string lhs, std::string rhs) { return replace_whitespace(lhs) < replace_whitespace(rhs); });
for ( const std::string& s : s3 ) { std::cout << to_display_string(s) << "\n"; }
std::vector<std::string> s4 = {
"cASE INDEPENENT: 3-2",
"caSE INDEPENENT: 3-1",
"casE INDEPENENT: 3+0",
"case INDEPENENT: 3+1"
};
std::cout << "\n";;
std::sort(s4.begin(), s4.end(),
[](std::string lhs, std::string rhs) { return to_lower_case(lhs) < to_lower_case(rhs); });
for ( const std::string& s : s4 ) { std::cout << s << "\n"; }
std::vector<std::string> s5 = {
"foo100bar99baz0.txt",
"foo100bar10baz0.txt",
"foo1000bar99baz10.txt",
"foo1000bar99baz9.txt"
};
std::cout << "\n";;
std::sort(s5.begin(), s5.end(),
[](std::string lhs, std::string rhs) { return zero_padding(lhs) < zero_padding(rhs); });
for ( const std::string& s : s5 ) { std::cout << s << "\n"; }
std::vector<std::string> s6 = {
"The Wind in the Willows",
"The 40th step more",
"The 39 steps",
"Wanda"
};
std::cout << "\n";;
std::sort(s6.begin(), s6.end(),
[](std::string lhs, std::string rhs) { return remove_title(lhs) < remove_title(rhs); });
for ( const std::string& s : s6 ) { std::cout << s << "\n"; }
std::vector<std::string> s7 = {
"Equiv. ý accents: 2-2",
"Equiv. Ý accents: 2-1",
"Equiv. y accents: 2+0",
"Equiv. Y accents: 2+1"
};
std::cout << "\n";;
std::sort(s7.begin(), s7.end(),
[](std::string lhs, std::string rhs) { return replace_accents(lhs) < replace_accents(rhs); });
for ( const std::string& s : s7 ) { std::cout << s << "\n"; }
std::vector<std::string> s8 = {
"IJ ligatured ij",
"no ligature"
};
std::cout << "\n";;
std::sort(s8.begin(), s8.end(),
[](std::string lhs, std::string rhs) { return replace_ligatures(lhs) < replace_ligatures(rhs); });
for ( const std::string& s : s8 ) { std::cout << s << "\n"; }
std::vector<std::string> s9 = {
"Start with an ʒ: 2-2",
"Start with an ſ: 2-1",
"Start with an ß: 2+0",
"Start with an s: 2+1"
};
std::cout << "\n";;
std::sort(s9.begin(), s9.end(),
[](std::string lhs, std::string rhs) { return replace_characters(lhs) < replace_characters(rhs); });
for ( const std::string& s : s9 ) { std::cout << s << "\n"; }
}

View file

@ -0,0 +1,227 @@
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public final class NaturalSorting {
public static void main(String[] args) {
System.out.println("The 9 string lists, sorted 'naturally':");
List<String> s1 = Arrays.asList(
"ignore leading spaces: 2-2",
" ignore leading spaces: 2-1",
" ignore leading spaces: 2+0",
" ignore leading spaces: 2+1"
);
System.out.println();
s1.sort(comparator1);
s1.forEach(System.out::println);
List<String> s2 = Arrays.asList(
"ignore m.a.s spaces: 2-2",
"ignore m.a.s spaces: 2-1",
"ignore m.a.s spaces: 2+0",
"ignore m.a.s spaces: 2+1"
);
System.out.println();
s2.sort(comparator2);
s2.forEach(System.out::println);
List<String> s3 = Arrays.asList(
"Equiv. spaces: 3-3",
"Equiv.\rspaces: 3-2",
"Equiv.\u000cspaces: 3-1",
"Equiv.\u000bspaces: 3+0",
"Equiv.\nspaces: 3+1",
"Equiv.\tspaces: 3+2"
);
System.out.println();
s3.sort(comparator3);
s3.forEach( s -> System.out.println(toDisplayString(s) ));
List<String> s4 = Arrays.asList(
"cASE INDEPENENT: 3-2",
"caSE INDEPENENT: 3-1",
"casE INDEPENENT: 3+0",
"case INDEPENENT: 3+1"
);
System.out.println();
s4.sort(comparator4);
s4.forEach(System.out::println);
List<String> s5 = Arrays.asList(
"foo100bar99baz0.txt",
"foo100bar10baz0.txt",
"foo1000bar99baz10.txt",
"foo1000bar99baz9.txt"
);
System.out.println();
s5.sort(comparator5);
s5.forEach(System.out::println);
List<String> s6 = Arrays.asList(
"The Wind in the Willows",
"The 40th step more",
"The 39 steps",
"Wanda"
);
System.out.println();
s6.sort(comparator6);
s6.forEach(System.out::println);
List<String> s7 = Arrays.asList(
"Equiv. ý accents: 2-2",
"Equiv. Ý accents: 2-1",
"Equiv. y accents: 2+0",
"Equiv. Y accents: 2+1"
);
System.out.println();
s7.sort(comparator7);
s7.forEach(System.out::println);
List<String> s8 = Arrays.asList(
"IJ ligatured ij",
"no ligature"
);
System.out.println();
s8.sort(comparator8);
s8.forEach(System.out::println);
List<String> s9 = Arrays.asList(
"Start with an ʒ: 2-2",
"Start with an ſ: 2-1",
"Start with an ß: 2+0",
"Start with an s: 2+1"
);
System.out.println();
s9.sort(comparator9);
s9.forEach(System.out::println);
}
/** Ignoring leading space(s) */
private static Comparator<String> comparator1 = Comparator.comparing(String::stripLeading);
/** Ignoring multiple adjacent spaces, that is, condensing to a single space */
private static Comparator<String> comparator2 =
(s1, s2) -> s1.replaceAll("[ ]{2,}", " ").compareTo(s2.replaceAll("[ ]{2,}", " "));
/** Equivalent whitespace characters (all equivalent to a single space) */
private static Comparator<String> comparator3 =
(s1, s2) -> s1.replaceAll("\\s+", " ").compareTo(s2.replaceAll("\\s+", " "));
/** Case independent sort */
private static Comparator<String> comparator4 = Comparator.comparing(String::toLowerCase);
/** Numeric fields as numerics (deals with numbers up to 20 digits) */
private static Comparator<String> comparator5 = Comparator.comparing(NaturalSorting::zeroPadding);
/** Title sort */
private static Comparator<String> comparator6 = (s1, s2) ->
s1.replaceFirst("^The\s+|^An\s+|^A\s+", "").compareTo(s2.replaceFirst("^The\s+|^An\s+|^A\s+", ""));
/** Equivalent accented characters */
private static Comparator<String> comparator7 = Comparator.comparing(NaturalSorting::replaceAccents);
/** Separated ligatures */
private static Comparator<String> comparator8 = Comparator.comparing(NaturalSorting::replaceLigatures);
/** Character replacements */
private static Comparator<String> comparator9 = Comparator.comparing(NaturalSorting::replaceCharacters);
/** Display strings including whitespace as if the latter were literal characters */
private static String toDisplayString(String text) {
List<String> whitespace1 = List.of( "\t", "\n", "\u000b", "\u000c", "\r" );
List<String> whitespace2 = List.of( "\\t", "\\n", "\\u000b", "\\u000c", "\\r" );
for ( int i = 0; i < whitespace1.size(); i++ ) {
text = text.replace(whitespace1.get(i), whitespace2.get(i));
}
return text;
}
/** Pad each numeric character with leading zeros to a total length of 20 */
private static String zeroPadding(String text) {
Pattern pattern = Pattern.compile("-?\\d+");
Matcher matcher = pattern.matcher(text);
StringBuilder result = new StringBuilder();
int index = 0;
while ( matcher.find() ) {
result.append(text.substring(index, matcher.start()));
result.append("0".repeat(20 - ( matcher.end() - matcher.start() )));
result.append(text.substring(matcher.start(), matcher.end()));
index = matcher.end();
}
result.append(text.substring(index));
return result.toString();
}
/** Replace accented letters with their unaccented equivalent */
private static String replaceAccents(String text) {
StringBuilder stringBuilder = new StringBuilder();
for ( int i = 0; i < text.length(); i++ ) {
final String letter = text.substring(i, i + 1);
if ( ( text.charAt(i) & 0xff ) < 128 ) {
stringBuilder.append(letter);
continue;
}
final int length = stringBuilder.length();
for ( int j = 0; j < ucAccents.size(); j++ ) {
if ( ucAccents.get(j).contains(letter) ) {
stringBuilder.append(ucUnaccents.get(j));
break;
}
}
if ( length == stringBuilder.length() ) {
for ( int j = 0; j < lcAccents.size(); j++ ) {
if ( lcAccents.get(j).contains(letter) ) {
stringBuilder.append(lcUnaccents.get(j));
break;
}
}
}
}
return stringBuilder.toString();
}
/** Replace ligatures with separated letters */
private static String replaceLigatures(String text) {
for ( int i = 0; i < ucLigatures.size(); i++ ) {
text = text.replace(ucLigatures.get(i), ucSeparates.get(i));
}
for ( int i = 0; i < lcLigatures.size(); i++ ) {
text = text.replace(lcLigatures.get(i), lcSeparates.get(i));
}
return text;
}
/** Replace miscellaneous letters with their equivalent replacements */
private static String replaceCharacters(String text) {
for ( int i = 0; i < miscLetters.size(); i++ ) {
text = text.replace(miscLetters.get(i), miscReplacements.get(i));
}
return text;
}
/** Only covers ISO-8859-1 accented characters plus, for consistency, Ÿ */
private static final List<String> ucAccents =
List.of( "ÀÁÂÃÄÅ", "Ç", "ÈÉÊË", "ÌÍÎÏ", "Ñ", "ÒÓÔÕÖØ", "ÙÚÛÜ", "ÝŸ" );
private static final List<String> lcAccents =
List.of( "àáâãäå", "ç", "èéêë", "ìíîï", "ñ", "òóôõöø", "ùúûü", "ýÿ" );
private static final List<String> ucUnaccents = List.of( "A", "C", "E", "I", "N", "O", "U", "Y" );
private static final List<String> lcUnaccents = List.of( "a", "c", "e", "i", "n", "o", "u", "y" );
/** Only the more common ligatures */
private static final List<String> ucLigatures = List.of( "Æ", "IJ", "Œ" );
private static final List<String> lcLigatures = List.of( "æ", "ij", "œ" );
private static final List<String> ucSeparates = List.of( "AE", "IJ", "OE" );
private static final List<String> lcSeparates = List.of( "ae", "ij", "oe" );
/** Miscellaneous replacements */
private static final List<String> miscLetters = List.of( "ß", "ſ", "ʒ" );
private static final List<String> miscReplacements = List.of( "ss", "s", "s" );
}