问题
I've been working on ordering of object which need to be done on the string which has integer value like "1","2". But LINQ OrderBy or SOrt inplace itself not ordering correctly :
Following code can reproduce my issue :
var listStr = new List<string>()
{
"1",
"100",
"12"
};
var sortedList = listStr.OrderBy(x => x);
var desList = listStr.OrderByDescending(x => x);
Here, SortedList is in following order : "1","100","12" and deslist is "12","100", "12"
I am confused with the way with string comparison done in ordering by C#. I am interested in the reasoning behind not working.
回答1:
This particular question comes up all the time and I'm pretty sure there are good duplicate questions here on Stack Overflow covering the topic. Please close the question as a proper duplicate and I'd be more than happy to delete my answer in response.
In the meantime...
The problem is us humans.
We see numbers so we think in numbers. To us, 1 is less than 12, and 12 is less than 100. No problems here.
The problem, however, is that we're asking a computer. And a computer is a bit more finicky. In particular, if we're asking a computer to do a alphabetical sort, it will invariably treat our "things" to sort as text. And this is where the problems occur. Or rather, this is where our expectations no longer match what the computer is going to do.
The computer, when asked to sort strings, sort them as any other string sort, character by character.
Let's look at the items:
1
100
12
To us, the natural sort order would be 1, 12, 100. Increasing order.
To the computer, asked to do a text sort, the natural order is different.
The reason is that it's going to compare strings one character at a time.
Broadly it is going to say "all strings that start with 1 is going to come before strings that start with 2", which means "1" and "100" is going to come before "2". This is exactly the same as saying "all words that start with the letter A comes before words that start with the letter B".
Then it's going to say "all strings that then have a 0 comes before strings that have a 1, 2, 3, etc. up to 9, including space", because this is how text sorting is done.
In other words, when you ask "Sort does not order correctly for integer string list?" the simple answer is "Well, no, because when you sort as text, the integer part is never considered".
回答2:
You're performing a lexicographical sort (i.e. an alphabetical sort) since you are sorting strings, not ints.
var listStr = new List<int>()
{
1,
100,
12
};
var sortedList = listStr.OrderBy(x => x);
var desList = listStr.OrderByDescending(x => x);
will do what you're looking to do.
EDIT to explain why the lexicographical sort is ordering things the way it is: Let's pretend we have a list of B, BAA, and BC. If you sort them alphabetically you get B, BAA, and BC. The same sort logic holds true when we are dealing with lists of strings as ints. "1" will come first (since it is like "B"), "100" will be second (since it is like BAA), and "12" will be the last (since it is like "BC").
回答3:
- Fact:
12
is less than100
. - Fact
"12"
is "greater" than"100"
.
When comparing numbers the numerical value is used to determine which number is greater.
When comparing strings the individual characters are used. Instead of thinking of a string as a whole think of it by character. So, "12"
is really { '1', '2' }
& "100"
is { '1', '0', '0' }
.
When sorting "12"
and "100"
the first character is compared in each - 1
& 1
- both the same so we must move on to the next character - 2
& 0
- and 2
is greater than 0
so we can immediately say "12"
is greater than "100"
. There's no need to even look at the final 0
in "100"
.
回答4:
As mentioned in the comments, since you are storing the data as strings, it's going to sort based off the string value of the variable.
Think of it alphabetically, which is first, bc or baa. Note that a=0, b=1, c=2 in this example.
Without changing the definition of your variable, the following code should work.
var sortedList = listStr.OrderBy(x => int.Parse(x));
var desList = listStr.OrderByDescending(x => int.Parse(x));
来源:https://stackoverflow.com/questions/40942428/linq-orderby-or-sort-does-not-order-correctly-for-integer-string-list