按文化排序未按预期工作
order by culture is not working as expected
为什么“Ū”排在第一位而不是 "U"?
CultureInfo ci = CultureInfo.GetCultureInfo("lt-LT");
bool ignoreCase = true; //whether comparison should be case-sensitive
StringComparer comp = StringComparer.Create(ci, ignoreCase);
string[] unordered = { "Za", "Žb", "Ūa", "Ub" };
var ordered = unordered.OrderBy(s => s, comp);
订购结果:
Ūa
Ub
杂
兹布
应该是:Ub Ūa Za Žb
我刚刚为您的问题做了一个(有限的)解决方案。
这不是优化的,但它可以给出如何解决它的想法。
我创建了一个 LithuanianString
class 仅用于封装您的字符串。
class 实现 IComparable
以便能够对 LithuanianString
的列表进行排序。
这可能是 class:
public class LithuanianString : IComparable<LithuanianString>
{
const string UpperAlphabet = "AĄBCČDEĘĖFGHIĮYJKLMNOPRSŠTUŲŪVZŽ";
const string LowerAlphabet = "aąbcčdeęėfghiįyjklmnoprsštuųūvzž";
public string String;
public LithuanianString(string inputString)
{
this.String = inputString;
}
public int CompareTo(LithuanianString other)
{
var maxIndex = this.String.Length <= other.String.Length ? this.String.Length : other.String.Length;
for (var i = 0; i < maxIndex; i++)
{
//We make the method non case sensitive
var indexOfThis = LowerAlphabet.Contains(this.String[i])
? LowerAlphabet.IndexOf(this.String[i])
: UpperAlphabet.IndexOf(this.String[i]);
var indexOfOther = LowerAlphabet.Contains(other.String[i])
? LowerAlphabet.IndexOf(other.String[i])
: UpperAlphabet.IndexOf(other.String[i]);
if (indexOfOther != indexOfThis)
return indexOfThis - indexOfOther;
}
return this.String.Length - other.String.Length;
}
}
这是我制作的示例:
static void Main(string[] args)
{
string[] unordered = { "Za", "Žb", "Ūa", "Ub" };
//Create a list of lithuanian string from your array
var lithuanianStringList = (from unorderedString in unordered
select new LithuanianString(unorderedString)).ToList();
//Sort it
lithuanianStringList.Sort();
//Display it
Console.WriteLine(Environment.NewLine + "My Comparison");
lithuanianStringList.ForEach(c => Console.WriteLine(c.String));
}
输出是预期的:
Ub Ūa Za Žb
此 class 允许仅通过替换开头定义的两个常量中的字符来创建自定义字母表。
为什么“Ū”排在第一位而不是 "U"?
CultureInfo ci = CultureInfo.GetCultureInfo("lt-LT");
bool ignoreCase = true; //whether comparison should be case-sensitive
StringComparer comp = StringComparer.Create(ci, ignoreCase);
string[] unordered = { "Za", "Žb", "Ūa", "Ub" };
var ordered = unordered.OrderBy(s => s, comp);
订购结果: Ūa Ub 杂 兹布
应该是:Ub Ūa Za Žb
我刚刚为您的问题做了一个(有限的)解决方案。
这不是优化的,但它可以给出如何解决它的想法。
我创建了一个 LithuanianString
class 仅用于封装您的字符串。
class 实现 IComparable
以便能够对 LithuanianString
的列表进行排序。
这可能是 class:
public class LithuanianString : IComparable<LithuanianString>
{
const string UpperAlphabet = "AĄBCČDEĘĖFGHIĮYJKLMNOPRSŠTUŲŪVZŽ";
const string LowerAlphabet = "aąbcčdeęėfghiįyjklmnoprsštuųūvzž";
public string String;
public LithuanianString(string inputString)
{
this.String = inputString;
}
public int CompareTo(LithuanianString other)
{
var maxIndex = this.String.Length <= other.String.Length ? this.String.Length : other.String.Length;
for (var i = 0; i < maxIndex; i++)
{
//We make the method non case sensitive
var indexOfThis = LowerAlphabet.Contains(this.String[i])
? LowerAlphabet.IndexOf(this.String[i])
: UpperAlphabet.IndexOf(this.String[i]);
var indexOfOther = LowerAlphabet.Contains(other.String[i])
? LowerAlphabet.IndexOf(other.String[i])
: UpperAlphabet.IndexOf(other.String[i]);
if (indexOfOther != indexOfThis)
return indexOfThis - indexOfOther;
}
return this.String.Length - other.String.Length;
}
}
这是我制作的示例:
static void Main(string[] args)
{
string[] unordered = { "Za", "Žb", "Ūa", "Ub" };
//Create a list of lithuanian string from your array
var lithuanianStringList = (from unorderedString in unordered
select new LithuanianString(unorderedString)).ToList();
//Sort it
lithuanianStringList.Sort();
//Display it
Console.WriteLine(Environment.NewLine + "My Comparison");
lithuanianStringList.ForEach(c => Console.WriteLine(c.String));
}
输出是预期的:
Ub Ūa Za Žb
此 class 允许仅通过替换开头定义的两个常量中的字符来创建自定义字母表。