Tutorial :.net - Problems with Array.Sort and Array.BinarySearch - culture and globalization



Question:

I need to sort an array containing a list of words and search the same using binarysearch. For certain reasons, the word-list must always be sorted using the sorting-rules of "en-US" i.e. American Regional Settings. The code will run under various international Operating Systems and of course this will mean that the word-list will be sorted differently according to the local Regional Settings in use. One problem could arise on a computer/device running with Lithuanian Regional Settings. Why? Because the letter "Y" in most languages is sorted like X-Y-Z while in Lithuanian, the sort order is I-Y-J. This behavior would create havoc to my program.

On a desktop-PC, I could change momentarily the Regional Settings into American English by using:

Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("en-US")

however since I am developing for Windows Mobile (CF.NET), this piece of code is not possible to implement.

I found some hacks which could let me change the Regional Settings on the device programatically but they are not "official" and considered risky so I prefer avoiding these.

So my question is: how can I force Array.Sort and Array.BinarySearch to use CultureInfo = "en-US" while sorting and searching regardless of the Regional Settings set on the device?

I believe I could use:

Public Shared Function BinarySearch(Of T) ( _      array As T(), _      value As T, _      comparer As IComparer(Of T) _  ) As Integer  

and implement Comparer to take into consideration CultureInfo (and set it to "en-US") but I don't know how to do that despite trying hard. If anyone could post some sample-code in VB.Net or C# or an explanation how to do it, I would be very grateful.

If you are aware about any alternative solution which works in CF.Net, then of course I am all ears.

Thanks.

EDIT:

I will consider Twanfosson's answer as the accepted solution since my question clearly stated that I wanted to maintain an association with the English language.

However, in means of flexibility I believe Guffa's answer is the best one. Why? Let's use another example: In German, the letter Ö is sorted Ö-X-Z while in Swedish and Finnish, the order is X-Z-Ö. In Estonian the sort order is Z-Ö-X. Complicated, isn't it? Guffa's solution will let me force Swedish sorting-oder (changing CultureInfo) on a device running under German Regional settings. Using Comparer.DefaultInvariant with its association to English wouldn't help in this case, probably the letter Ö would end up with O. Therefore my vote will go to Guffa.


Solution:1

Is it not possible to use the Invariant culture?

InvariantCulture retrieves an instance of the invariant culture. It is associated with the English language but not with any country/region.

Using the invariant culture would make this trivial.

Array.Sort( myArray, Comparer.DefaultInvariant );    Array.BinarySearch( myArray, myString, Comparer.DefaultInvariant );  


Solution:2

Well, the answer to both is to implement a comparer. Create a class that implements the IComprarer(Of String) interface and has it's own CultureInfo object that it uses to compare the strings:

Public Class StringComparerEnUs     Implements IComparer(Of String)       Private _culture As CultureInfo       Public Sub New()        _culture = New CultureInfo("en-US")     End Sub       Public Function Compare(ByVal x As String, ByVal y As String)        Return String.Compate(x, y, false, _culture)     End Function    End Class  

Now you can use it to sort the strings:

Array.Sort(theArray, New StringComparerEnUs())  

and to find them:

pos = BinarySearch(theArray, "Dent, Arthur", new StringComparerEnUs())  

(The class can of course be made a bit more general by accepting a culture string in the constructor, and you can also add a variable to make use of the ignorecase parameter in the String.Compare call.)


Solution:3

Try this:

class EnglishComparer : IComparer<string>  {    static CultureInfo __english = new CultureInfo("en-US");      public int Compare(string x, string y)    {      return string.Compare(x, y, __english, CompareOptions.None);    }  }  

Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »