Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Easiest method to OrderBy a String using StringComparison.Ordinal

I've found a bug (in my code) that results from String.CompareTo and binary search because my custom IComparer (for the wrapping type) uses String.Compare(x, y, StringComparison.Ordinal).

This is because items.OrderBy(i => i.Name) (where Name is of type string) used to build the Array to search used the string object itself as the IComparable - and such has different rules:

The comparison uses the current culture to obtain culture-specific information such as casing rules and the alphabetic order of individual characters. For example, a culture could specify that certain combinations of characters be treated as a single character, or uppercase and lowercase characters be compared in a particular way, or that the sorting order of a character depends on the characters that precede or follow it.

For example, {A, b, C} is sorted as [A, b, C] with the OrderBy-using-Default-String-Compare but should be [b, A, C] per the Ordinal comparison - since it is not, the binary search is failing.

Now, with the "context" out of the way,

What is the easiest (eg. without implementing a custom IComparer for strings) way to order the objects with string properties the same as with String.Compare(.., StringComparison.Ordinal)?


Edit: I [just realized I] can, and probably should, just use OrderBy(x => x, theSameComparer) - but supposing this wasn't possible, how can OrderBy be used with the same results?

like image 672
user2864740 Avatar asked Feb 20 '15 21:02

user2864740


People also ask

What does StringComparison ordinal do?

The StringComparison enumeration is used to specify whether a string comparison should use the current culture or the invariant culture, word or ordinal sort rules, and be case-sensitive or case-insensitive. When you call a string comparison method such as String.

Does OrderBy work on string?

OrderBy" function utilizes the default comparer for a string. That comparer is not necessarily going to return a sort order based on the ASCII code. For a list of all the different string comparers, see the article on MSDN.

What is the use of StringComparison OrdinalIgnoreCase?

OrdinalIgnoreCase. The StringComparison has the OrdinalIgnoreCase property and treats the characters in the strings to compare as if they were converted to uppercase (using the conventions of the invariant culture) and then it performs a simple byte comparison and it is independent of language.


Video Answer


2 Answers

There is a pre-built StringComparer that applies StringComparison.Ordinal - that's StringComparer.Ordinal:

items.OrderBy(i => i.Name, StringComparer.Ordinal)
like image 63
Sergey Kalinichenko Avatar answered Sep 27 '22 21:09

Sergey Kalinichenko


You should be able to add StringComparer.Ordinal directly into your OrderBy.

string[] content = { "A", "b", "C", "d", "AB", "Ab" };
var ordered = content.OrderBy(o => o, StringComparer.Ordinal);

Then once you iterate through ordered you would receive the following output:

// Output:
A
AB
Ab
C
b
d

I believe that is what your after.

like image 23
Greg Avatar answered Sep 27 '22 21:09

Greg