简体   繁体   English

用Linq查找带负数的数字序列的最小值

[英]Find the minimum of a number sequence with negative numbers with Linq

The following code doesn't give the expected minimum -1. 以下代码未给出预期的最小值-1。 Instead I get 0. Do you know why? 相反,我得到0。您知道为什么吗?

class MainClass
{
    public static void Main (string[] args)
    {
        string numbers = "-1 0 1 2 3 4 5";
        Console.WriteLine (numbers.Split (' ')[0]);     // output: -1
        string max = numbers.Split(' ').Max();
        string min = numbers.Split(' ').Min();
        Console.WriteLine("{0} {1}", max, min);         // output: "5 0"
    }
}

It's a string so Getting max from string is totally different than getting max from a number. 这是一个字符串,因此从字符串中获取最大值与从数字中获取最大值完全不同。 For instance if You would have an array like below 例如,如果您将有一个如下所示的数组

char[] someCharArray = new char[] { '1', '12', '2' } char [] someCharArray = new char [] {'1','12','2'}

calling Max() on this array would result with 2 as 2 is "higher" in string order than 12. 在此数组上调用Max()将导致2,因为2在字符串顺序上比“ 12”“高”。

Thinking about Max/Min value from string/char You need to think about alphabetical order. 考虑字符串/字符的最大值/最小值您需要考虑字母顺序。 If You have a colection of letters AZ, calling Min() will return A, calling Max() will return Z. 如果您有字母AZ的集合,则调用Min()将返回A,调用Max()将返回Z。

To get Max/Min in numerical order You need to cast to some Number type like int. 要按数字顺序获得最大/最小,您需要转换为一些数字类型,例如int。 See below: 见下文:

string numbers = "-1 0 1 2 3 4 5";
int min = numbers.Split(' ').Select(x => int.Parse(x)).Min();
Console.WriteLine(min); // gives You -1

I've not fully defined an answer yet but it appears to be because the - isn't accounted for.. you can confirm this with CompareOrdinal 我还没有完全定义一个答案,但这似乎是因为-没有说明..您可以使用CompareOrdinal进行确认

    Console.WriteLine(String.CompareOrdinal("-1", "0"));  // -3 meaning -1 min
    Console.WriteLine(String.Compare("-1", "0"));  // 1 meaning 0 min

Either way, you are trying to compare numbers so you should treat them as numbers so similar subtleties dont appear. 无论哪种方式,您都尝试比较数字,因此应将它们视为数字,以免出现类似的细微差别。


Attempted explanation... 尝试说明...

String implements IComparable<string> so String.Min uses that implementation (see remarks). String实现IComparable<string>因此String.Min使用该实现(请参见备注)。 Which in turn uses CompareTo , 依次使用CompareTo

Now in the notes for this method 现在在此方法的注释中

Character sets include ignorable characters. 字符集包括可忽略的字符。 The CompareTo(String) method does not consider such characters when it performs a culture-sensitive comparison. 在执行对区域性敏感的比较时,CompareTo(String)方法不考虑此类字符。 For example, if the following code is run on the .NET Framework 4 or later, a comparison of "animal" with "ani-mal" (using a soft hyphen, or U+00AD) indicates that the two strings are equivalent. 例如,如果以下代码在.NET Framework 4或更高版本上运行,则“ animal”“ ani-mal” (使用软连字符或U + 00AD)的比较表明这两个字符串是等效的。

(Emphasis mine) (强调我的)

As you see. 正如你看到的。 the - is ignored hence 0 which has a smaller value in an ascii table is used for the comparison -被忽略,因此在ascii表中具有较小值的0用于比较

There are two reasons for this behaviour: 此行为有两个原因:

  1. You are sorting strings instead of numbers. 您正在对字符串而不是数字进行排序。 This means that behind the scenes, Linq is using String.CompareTo() to compare the strings. 这意味着在后台,Linq使用String.CompareTo()比较字符串。
  2. String.CompareTo() has special behaviour for - , which it treats as a HYPHEN and not a MINUS. String.CompareTo()对于-具有特殊行为,将其视为连字符而不是减号。 (Note: This hyphen should not be confused with a soft hyphen which has the character code U00AD.) (注意:此连字符不应与字符代码为U00AD的软连字符混淆。)

Consider this code: 考虑以下代码:

Console.WriteLine("-1".CompareTo("0")); // 1
Console.WriteLine("-1".CompareTo("1")); // 1
Console.WriteLine("-1".CompareTo("2")); // -1

Notice how, counter-intuitively, the "-1" is AFTER "0" and "1" but BEFORE "2". 与直觉相反,请注意“ -1”是在“ 0”和“ 1”之后,还是在“ 2”之前。

This explains why when ordering the strings, the "-1" is neither the max nor the min. 这解释了为什么在订购字符串时,“-1”既不是最大值也不是最小值。

Also see the answer to this question for more details. 另请参阅此问题的答案以获取更多详细信息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM