Jump to content

ANSI compare strings (for sort array)


Zedna
 Share

Recommended Posts

I need something like AnsiCompare() in Delphi

which uses WIN API CompareString with LOCALE_USER_DEFAULT

I need sort array with names of peoples containing accents (diacritics)

<array.au3> --> _ArraySort() is not working fine

I searched forum for use of CompareString API but didn't find nothing :P

Please is there some finished code for this, so I needn't do it from scratch?

I mean ANSI compare and sort.

Thank you

Link to comment
Share on other sites

I need something like AnsiCompare() in Delphi

which uses WIN API CompareString with LOCALE_USER_DEFAULT

I need sort array with names of peoples containing accents (diacritics)

<array.au3> --> _ArraySort() is not working fine

I searched forum for use of CompareString API but didn't find nothing :P

Please is there some finished code for this, so I needn't do it from scratch?

I mean ANSI compare and sort.

Thank you

do you have some sample data?

Link to comment
Share on other sites

here's something you might be able to work with, if you need to have multiple flags just bitor them

Const $LOCALE_USER_DEFAULT = 0x400
Const $LOCALE_SYSTEM_DEFAULT = 0x800 
;~ Ignore case.
Const $NORM_IGNORECASE = 0x1
;~ Do not differentiate between Hiragana and Katakana characters. 
;~ Corresponding Hiragana and Katakana characters compare as equal.
Const $NORM_IGNOREKANATYPE = 0x40
;~ Ignore nonspacing characters.
Const $NORM_IGNORENONSPACE = 0x2
;~ Ignore symbols.
Const $NORM_IGNORESYMBOLS = 0x4 
;~ Do not differentiate between a single-byte character and the same 
;~ character as a double-byte character.
Const $NORM_IGNOREWIDTH = 0x8
;~ Treat punctuation the same as symbols.
Const $SORT_STRINGSORT = 0x1000 
$str1 = "don't"
$str2 = "do not"
$a_ret = DllCall("kernel32.dll","int","CompareString","int",$LOCALE_USER_DEFAULT, "int", _
    $NORM_IGNORECASE, "str", $str1, "int", -1, "str", $str2, "int", -1)

;~ If the function succeeds, the return value is one of the following values. 

;~ The string pointed to by the lpString1 parameter is less in lexical value than the string 
;~ pointed to by the lpString2 parameter.The string pointed to by lpString1 is equivalent in
;~ lexical value to the string pointed to by lpString2. The two strings are equivalent for 
;~ collating purposes, though not necessarily identical.The string pointed to by lpString1 
;~ is greater in lexical value than the string pointed to by lpString2.

;~ If the function fails, the return value is zero. 
;~ To get extended error information, call GetLastError. 
;~ GetLastError may return one of the following error codes:

ConsoleWrite($a_ret[0] & @LF)
Edited by gafrost

SciTE for AutoItDirections for Submitting Standard UDFs

 

Don't argue with an idiot; people watching may not be able to tell the difference.

 

Link to comment
Share on other sites

here's something you might be able to work with, if you need to have multiple flags just bitor them

I did it, it sotrs fine :P

Thank you Gafrost.

For optimize reason there should be DllOpen at begin of _ArraySortLocale

and in CompareStringLocale should be new parameter $dll used in DllCall as handle of Dll

so at each comparing row we didn't do internal DllOpen / DllClose in DllCall

But for my use it's OK.

Const $LOCALE_USER_DEFAULT = 0x400

#include <Array.au3>

Dim $pole[4] = ['Zedna','Šilhan','Sečkář', 'Sedan']

_ArrayDisplay($pole,'before')
_ArraySort($pole)
_ArrayDisplay($pole,'after normal')
_ArraySortLocale($pole)
_ArrayDisplay($pole,'after locale')

Func CompareStringLocale($s1, $s2, $ignore_case = 0)
    $a_ret = DllCall("kernel32.dll","int","CompareString","int",$LOCALE_USER_DEFAULT, "int", _
                    $ignore_case, "str", $s1, "int", -1, "str", $s2, "int", -1)
    Return $a_ret[0]
EndFunc

Func _ArraySortLocale(ByRef $a_Array, $i_Decending = 0, $i_Base = 0, $i_UBound = 0)
 ; Set to ubound when not specified
    If Not IsArray($a_Array) Then
       SetError(1)
       Return 0
    EndIf
    Local $last = UBound($a_Array) - 1
    If $i_UBound < 1 Or $i_UBound > $last Then $i_UBound = $last
    
    __ArrayQSort1Locale($a_Array, $i_Base, $i_UBound)
    If $i_Decending Then _ArrayReverse($a_Array, $i_Base, $i_UBound)
        
    Return 1
EndFunc;==>_ArraySort

; Private
Func __ArrayQSort1Locale(ByRef $array, ByRef $left, ByRef $right)
    If $right - $left < 10 Then
     ; InsertSort - fastest on small segments (= 25% total speedup)
        Local $i, $j, $t
        For $i = $left + 1 To $right
            $t = $array[$i]
            $j = $i
            While $j > $left _  
                And CompareStringLocale(String($array[$j - 1]),String($t)) = 3; String($array[$j - 1]) > String($t)
                $array[$j] = $array[$j - 1]
                $j = $j - 1
            Wend
            $array[$j] = $t
        Next
        Return
    EndIf
    
 ; QuickSort - fastest on large segments
    Local $pivot = $array[Int(($left + $right)/2)];, $t
    Local $L = $left
    Local $R = $right
    Do
        While CompareStringLocale(String($array[$L]),String($pivot)) = 1; String($array[$L]) < String($pivot)
            $L = $L + 1
        Wend
        While CompareStringLocale(String($array[$R]),String($pivot)) = 3; String($array[$R]) > String($pivot)
            $R = $R - 1
        Wend
     ; Swap
        If $L <= $R Then
            $t = $array[$L]
            $array[$L] = $array[$R]
            $array[$R] = $t
            $L = $L + 1
            $R = $R - 1
        EndIf
    Until $L > $R
        
    __ArrayQSort1Locale($array, $left, $R)
    __ArrayQSort1Locale($array, $L, $right)
EndFunc
Link to comment
Share on other sites

I brought this up ages ago. Sorting should always be case sensitive otherwise the resulting sort is 'undefined'. _ArraySort() returns a differently sorted list depending on the original order because it is not case sensitive.

I already have a string compare function but the DLLcall might be faster, Ill have to try that out, thanks.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...