如何在Dart中对带有德国变音符的字符串列表进行排序?

时间:2019-05-04 20:58:37

标签: dart flutter

如何用变音符号排序列表? compareTo-Function会忽略这些单词,将单词放在列表的末尾。

main() {
  var fruits = ['Äpfel', 'Bananen', 'Orangen'];
  fruits.sort((a, b) => a.compareTo(b));
}

5 个答案:

答案 0 :(得分:1)

此类支持德语,土耳其语和弗伦什特殊字符:

它将所有字符串转换为小写,但是如果需要,您可以轻松地解决。

class Angliciser {
  static const Map _letterConversion = {
    // German characters
    "ä": "a",
    "ö": "o",
    "ü": "u",

    // Turkish characters (omitting already existing ones)
    "ğ": "g",
    "i̇": "i", // these are not the same
    "ş": "s",

    // French characters (omitting already existing ones)
    "ç": "c",
    "à": "a",
    "â": "a",
    "è": "e",
    "é": "e",
    "ê": "e",
    "ë": "e",
    "î": "i",
    "ï": "i",
    "ô": "o",
    "œ": "o",
    "ù": "u",
    "û": "u",
    "ÿ": "y",
  };

  static String convert(String str) {
    if (str == null || str.isEmpty) return str;

    final converted = [];
    var sourceSymbols = [];

    sourceSymbols = str.toLowerCase().split('');

    for (final element in sourceSymbols) {
      converted.add(_letterConversion.containsKey(element) ? _letterConversion[element] : element);
    }

    return converted.join();
  }
}

答案 1 :(得分:1)

有一个名为 diacritic 的包,可以让它变得简单。

https://pub.dev/packages/diacritic

只需将依赖项放在 pubspec.yml 中并使用它。

dependencies:
  diacritic: ^0.1.1

导入:

import 'package:diacritic/diacritic.dart';

并使用它:

var fruits = ['Äpfel', 'Bananen', 'Orangen'];
fruits.sort((a, b) => removeDiacritics(a).compareTo(removeDiacritics(b)));
print(fruits);

输出将是:

[Äpfel, Bananen, Orangen]

答案 2 :(得分:0)

这是我写过的第一个dart程序,所以也许有更好的方法可以做到这一点。但至少它能起作用:

// Class for comparing strings in an umlaut-agnostic way.
class UmlautCompare {
  Map<int,int> map;
  UmlautCompare() {
    map = new Map<int,int>();
    String umlauts = 'ÄÖÜäöü';
    String mapped  = 'AOUaou';
    for (int i = 0; i < umlauts.length; ++i) {
      map[umlauts.codeUnitAt(i)] = mapped.codeUnitAt(i);
    }
  }
  // Compare two strings treating umlauts as the respective non-umlaut characters.
  int compare(String a, String b) {
    int min = a.length;
    if (b.length < a.length) min = b.length;
    for (int i = 0; i < min; ++i) {
        int charA = a.codeUnitAt(i);
        int charB = b.codeUnitAt(i);
      if (map.containsKey(charA))
        charA = map[charA];
      if (map.containsKey(charB))
        charB = map[charB];
        if (charA < charB) return -1;
        else if (charA > charB) return 1;
    }
    // If we get here then the first min characters are equal.
    // The strings are equal if they have the same length.
    // If they have different length then the shorter string is considered less.
    if (a.length < b.length) return -1;
    else if (a.length > b.length) return 1;  
    return 0;
  }
}

main() {
  UmlautCompare cmp = new UmlautCompare();
  var fruits = ['Orangen', 'Äpfel', 'Bananen'];
  fruits.sort((a, b) => cmp.compare(a, b));//compareUmlaut(a, b));
  print(fruits);
}

答案 3 :(得分:0)

我已经基于@DanielJunglas的想法创建了自定义比较器。 他的代码不适用于波兰语,而且我认为它对德语也不利。它适用于波兰语,但可以用于任何语言,您只需要在地图中更改字母即可。它会忽略所有其他非字母符号。例如,如果您也想比较“ +”号并在其他字母前加上它,只需将其添加到编号最低的映射表中即可。如果有人有更简单的方法,请告诉我。我也是初学者。

main() {

var sample = ['Ónda', 'Orangen', 'Ąpfel', 'Okren', 'żarcik', 'Banen', 'Alpa', 'łąka', 'źrebak'];

PolishLettersCompare cmp = new PolishLettersCompare();
  sample.sort(
    (a, b) => cmp.compare(a, b)
  );
}

class PolishLettersCompare {
final Map<String, int> map = {
"A": 1,
"a": 2,
"Ą": 3,
"ą": 4,
"B": 5,
"b": 6,
"C": 7,
"c": 8,
"Ć": 9,
"ć": 10,
"D": 11,
"d": 12,
"E": 13,
"e": 14,
"Ę": 15,
"ę": 16,
"F": 17,
"f": 18,
"G": 19,
"g": 20,
"H": 21,
"h": 22,
"I": 23,
"i": 24,
"J": 25,
"j": 26,
"K": 27,
"k": 28,
"L": 29,
"l": 30,
"Ł": 31,
"ł": 32,
"M": 33,
"m": 34,
"N": 35,
"n": 36,
"Ń": 37,
"ń": 38,
"O": 39,
"o": 40,
"Ó": 41,
"ó": 42,
"P": 43,
"p": 44,
"R": 45,
"r": 46,
"S": 47,
"s": 48,
"Ś": 49,
"ś": 50,
"T": 51,
"t": 52,
"U": 53,
"u": 54,
"V": 55,
"v": 56,
"W": 57,
"w": 58,
"X": 59,
"x": 60,
"Y": 61,
"y": 62,
"Z": 63,
"z": 64,
"Ż": 65,
"ż": 66,
"Ź": 67,
"ź": 68,
};
int charAint;
int charBint;
int compare(String a, String b) {
int min = a.length;
if (b.length < a.length) min = b.length;
for (int i = 0; i < min; ++i) {
  String charA = a[i];
  String charB = b[i];
  if (map.containsKey(charA)) {
    charAint = map[charA];
  }
  if (map.containsKey(charB)) {
    charBint = map[charB];
  }
  if (charAint > charBint)
    return 1;
  else if (charAint < charBint) return -1;
}
if (a.length < b.length)
  return -1;
else if (a.length > b.length) return 1;
return 0;
}
}

答案 4 :(得分:0)

这是我对以前答案的修改版本:

import 'dart:math';
static int compare(String a, String b) {
var letters = [
  "a",
  "ą",
  "b",
  "c",
  "ć",
  "d",
  "e",
  "ę",
  "f",
  "g",
  "h",
  "i",
  "j",
  "k",
  "l",
  "ł",
  "m",
  "n",
  "ń",
  "o",
  "ó",
  "p",
  "q",
  "r",
  "s",
  "ś",
  "t",
  "u",
  "v",
  "w",
  "x",
  "y",
  "z",
  "ż",
  "ź",
];

a = a.toLowerCase();
b = b.toLowerCase();

for (var i = 0; i < min(a.length, b.length); i++) {
  var aValue = letters.indexOf(a[i]);
  var bValue = letters.indexOf(b[i]);

  var result = (aValue - bValue).sign;
  if (result != 0) {
    return result;
  }
}

return (a.length - b.length).sign;

}

它的性能可能更差,但更容易阅读。