c#中字符串数组的最大和最小值



我最近开始学习Linq。我遇到了一些内置方法,如Min()和Max()。对于int[],这两个方法的工作很好。但是当涉及到string[]时,我很好奇它是如何工作的。我已经尝试了一些代码

string[] cars = { "Volvo", "BMW", "Ford", "Mazda" };
Console.WriteLine(cars.Max());
Console.WriteLine(cars.Min());

输出如下:

**Volvo for Max()

BMW for Min()**

你能解释一下它是如何工作的,它是按字母顺序取第一个字母,还是有任何机制,它是使用如基于ASCII值等?

所有实现IComparable或IComparable接口的类型都可以通过使用每个类型实现的CompareTo方法进行比较。所有原语类型都实现IComparable<T>,包括charstring。LINQ的Min(IEnumerable)Max(IEnumerable)使用这个实现来查找可枚举对象中的最小值或最大值。

字符串比较

比较字符串要比比较整数有趣一些。字符串通常按字典顺序(按字典顺序)进行比较,但是…他的字典吗?不同的语言有不同的排序规则,有时两个字母被认为是一个字母。即使丹麦人也忘记了AA在丹麦语中相当于Å

用于比较字符串的字典由CultureInfo类提供。默认情况下,使用当前线程的区域性,它通常与最终用户的区域性(在桌面应用程序中)或服务器应用程序中的系统区域设置相匹配。例如,在丹麦文化中,AAaa的对待方式是不同的——我认为其中一个是在相同大小写的其他字母之后排序的,而另一个不是,但不要问我是哪个。

InvariantCulture指定敏感区域性中的区域设置,该区域设置可用于在每个区域设置中以相同的方式处理字符串。它主要使用合理的设置(例如小数点为.),除了日期,它使用美国格式而不是每个人都期望的ISO8601 (YYYY-MM-DD)格式。

自定义比较

可以通过将实现IComparer的类传递给受顺序影响的LINQ方法来指定不同的比较方法。Min(IEnumerable, iccompparer)就是一个例子。

StringComparer类包含一些预定义的比较器:

  • CurrentCulture是默认的
  • CurrentCultureIgnoreCase使用当前区域性,但忽略大小写,因此A等于a。这是非常有用的,例如在字典中。
  • InvariantCulture和InvariantCultureIgnoreCase使用不变区域性排序
  • 最后,Ordinal和OrdinalIgnoreCase使用字典,而是比较字符的Unicode值。如果你不关心语言环境规则,这是最快的选择

.Max()使用Compare(String, String)它比较两个指定的String对象,并返回一个整数,指示它们在排序顺序中的相对位置。

.Max()字符串比较的源代码

public static TSource Max<TSource>(this IEnumerable<TSource> source) {
if (source == null) throw Error.ArgumentNull("source");
Comparer<TSource> comparer = Comparer<TSource>.Default;
TSource value = default(TSource);
if (value == null) {
foreach (TSource x in source) {
if (x != null && (value == null || comparer.Compare(x, value) > 0))
value = x;
}
return value;
}
else {
bool hasValue = false;
foreach (TSource x in source) {
if (hasValue) {
if (comparer.Compare(x, value) > 0) //Compare strings
value = x;
}
else {
value = x;
hasValue = true;
}
}
if (hasValue) return value;
throw Error.NoElements();
}
}

比较(字符串,字符串)https://learn.microsoft.com/en us/dotnet/api/system.string.compare?view=net - 6.0 # system-string-compare (system-string-system-string)

字符串按字母顺序进行比较,这转化为以下逻辑:

  • 哪个物品的首字符更高
  • 哪个物品的第二个字符更高
  • 哪个物品有更高的第三个字符

从第一个不同的字符开始检测差异。因此,当比较string1string2时,如果在它们的第一个不同字符处(从左到右),string1在该位置的值大于string2,则string1大于string2。如果string2=string1+string3,则string1string2的第一个差值超出了string1的末尾,此时比较得出string2大于string1

如果您对这个比较不满意,那么您可以指定您打算使用哪个比较器,参见这里:https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable.max?view=net-6.0#system-linq-enumerable-max-1(system-collections-generic-ienumerable((-0))-system-collections-generic-icomparer((-0)))

基本上在这种情况下,你需要实现一个IComparer并将其作为第二个参数传递,如

cars.Max(c => c, yourcomparer)

对于字符串列表,Min()或Max()分别跟随第一个和最后一个单词或字母,但对于整数,Min()或Max()遵循从列表中查找最小和最大数字的确切现象。请检查此图像及其输出