使用 AutoIt 的用户定义排序比较
Posted
技术标签:
【中文标题】使用 AutoIt 的用户定义排序比较【英文标题】:User-defined sorting comparison using AutoIt 【发布时间】:2018-09-16 01:23:10 【问题描述】:php 有usort,Java 有Comparator 接口。
这些允许您创建一个简单的函数来比较两个对象、字符串等,而无需参与排序实现的细节。
一般来说,比较函数是这样的:
// Return value:
// Negative value: a before b
// Positive value: b before a
// Zero: strings are equal
function compare(String a, String b)
return toLowerCase(a) - toLowerCase(b);
...您可以随心所欲地进行比较。
AutoIt 中有什么可以做到这一点的吗?
文档很棒,帮助文件也很棒,但是我找不到任何可以让我定义自定义比较函数的东西。 (如有必要,我将重新实现 Quicksort,但使用像 AutoIt 这样功能齐全的框架,我觉得我一定只是忽略了一些东西。)
【问题讨论】:
【参考方案1】:“AutoIt 中有什么可以做到这一点的吗?”
以_ArrayMultiColSort()
为例:
#include <Array.au3>
#include "ArrayMultiColSort.au3"
Global Const $g_sHeaderRow = 'category|value'
Global Const $g_aSortOrder = [ _
[0, 'critical,important,regular'], _
[1, 1] _
]
Global $g_aArray = [ _
['critical', 7], _
['important', 2], _
['important', 6], _
['regular', 2], _
['critical', 5], _
['regular', 9] _
]
_ArrayMultiColSort($g_aArray, $g_aSortOrder)
_ArrayDisplay($g_aArray, @ScriptName, '', 0, Default, $g_sHeaderRow)
返回:
critical 7
critical 5
important 6
important 2
regular 9
regular 2
【讨论】:
【参考方案2】:虽然 AutoIt 中似乎没有内置任何内容,但继续研究表明社区创建了几个非常有用的库。
下面是 Erik Pilsits 称为 _ArrayCustomSort.au3
的一个。脚本已在本文末尾复制以供参考。原文可以在这里找到:
https://www.autoitscript.com/forum/topic/83626-natural-order-string-comparison/
用法:
#include <File.au3>
#include "_ArrayCustomSort.au3"
; Directory to list files
Local $dir = "C:\Windows"
Local $arr = _FileListToArray($dir, "*")
_ArrayDelete($arr, 0)
; Here is the name of the user-defined sorting function!
_ArrayCustomSort($arr, "_MyBasicStringCompare", 0)
_ArrayDisplay($arr)
; Now you can put all your crazy sorting logic in here!
Func _MyBasicStringCompare($s1, $s2)
Return StringCompare($s1, $s2)
EndFunc
包含库:
#include-once
#include <Array.au3>
; #FUNCTION# ====================================================================================================================
; Name ..........: _ArrayCustomSort
; Description ...: Sort a 1D or 2D array on a specific index using the quicksort/insertionsort algorithms, based on a custom sorting function.
; Syntax ........: _ArrayCustomSort(Byref $avArray, $sSortFunc[, $iDescending = 0[, $iStart = 0[, $iEnd = 0[, $iSubItem = 0]]]])
; Parameters ....: $avArray - [in/out] Array to sort
; $sSortFunc - Name of custom sorting function. See Remarks for usage.
; $iDescending - [optional] If set to 1, sort descendingly
; $iStart - [optional] Index of array to start sorting at
; $iEnd - [optional] Index of array to stop sorting at
; $iSubItem - [optional] Sub-index to sort on in 2D arrays
; Return values .: Success - 1
; Failure - 0, sets @error:
; |1 - $avArray is not an array
; |2 - $iStart is greater than $iEnd
; |3 - $iSubItem is greater than subitem count
; |4 - $avArray has too many dimensions
; |5 - Invalid sort function
; Author ........: Erik Pilsits
; Modified ......: Erik Pilsits - removed IsNumber testing, LazyCoder - added $iSubItem option, Tylo - implemented stable QuickSort algo, Jos van der Zande - changed logic to correctly Sort arrays with mixed Values and Strings, Ultima - major optimization, code cleanup, removed $i_Dim parameter
; Remarks .......: Sorting function is called with two array elements as arguments. The function should return
; 0 if they are equal,
; -1 if element one comes before element two,
; 1 if element one comes after element two.
; Related .......:
; Link ..........:
; Example .......: No
; ===============================================================================================================================
Func _ArrayCustomSort(ByRef $avArray, $sSortFunc, $iDescending = 0, $iStart = 0, $iEnd = 0, $iSubItem = 0)
If Not IsArray($avArray) Then Return SetError(1, 0, 0)
If Not IsString($sSortFunc) Then Return SetError(5, 0, 0)
Local $iUBound = UBound($avArray) - 1
; Bounds checking
If $iEnd < 1 Or $iEnd > $iUBound Then $iEnd = $iUBound
If $iStart < 0 Then $iStart = 0
If $iStart > $iEnd Then Return SetError(2, 0, 0)
; Sort
Switch UBound($avArray, 0)
Case 1
__ArrayCustomQuickSort1D($avArray, $sSortFunc, $iStart, $iEnd)
If $iDescending Then _ArrayReverse($avArray, $iStart, $iEnd)
Case 2
Local $iSubMax = UBound($avArray, 2) - 1
If $iSubItem > $iSubMax Then Return SetError(3, 0, 0)
If $iDescending Then
$iDescending = -1
Else
$iDescending = 1
EndIf
__ArrayCustomQuickSort2D($avArray, $sSortFunc, $iDescending, $iStart, $iEnd, $iSubItem, $iSubMax)
Case Else
Return SetError(4, 0, 0)
EndSwitch
Return 1
EndFunc ;==>_ArrayCustomSort
; #INTERNAL_USE_ONLY#============================================================================================================
; Name...........: __ArrayCustomQuickSort1D
; Description ...: Helper function for sorting 1D arrays
; Syntax.........: __ArrayCustomQuickSort1D(ByRef $avArray, ByRef $sSortFunc, ByRef $iStart, ByRef $iEnd)
; Parameters ....: $avArray - Array to sort
; $sSortFunc - Name of sorting function.
; $iStart - Index of array to start sorting at
; $iEnd - Index of array to stop sorting at
; Return values .: None
; Author ........: Jos van der Zande, LazyCoder, Tylo, Ultima
; Modified.......: Erik Pilsits - removed IsNumber testing
; Remarks .......: For Internal Use Only
; Related .......:
; Link ..........;
; Example .......;
; ===============================================================================================================================
Func __ArrayCustomQuickSort1D(ByRef $avArray, ByRef $sSortFunc, ByRef $iStart, ByRef $iEnd)
If $iEnd <= $iStart Then Return
Local $vTmp
; InsertionSort (faster for smaller segments)
If ($iEnd - $iStart) < 15 Then
Local $i, $j
For $i = $iStart + 1 To $iEnd
$vTmp = $avArray[$i]
For $j = $i - 1 To $iStart Step -1
If (Call($sSortFunc, $vTmp, $avArray[$j]) >= 0) Then ExitLoop
$avArray[$j + 1] = $avArray[$j]
Next
$avArray[$j + 1] = $vTmp
Next
Return
EndIf
; QuickSort
Local $L = $iStart, $R = $iEnd, $vPivot = $avArray[Int(($iStart + $iEnd) / 2)]
Do
While (Call($sSortFunc, $avArray[$L], $vPivot) < 0)
$L += 1
WEnd
While (Call($sSortFunc, $avArray[$R], $vPivot) > 0)
$R -= 1
WEnd
; Swap
If $L <= $R Then
$vTmp = $avArray[$L]
$avArray[$L] = $avArray[$R]
$avArray[$R] = $vTmp
$L += 1
$R -= 1
EndIf
Until $L > $R
__ArrayCustomQuickSort1D($avArray, $sSortFunc, $iStart, $R)
__ArrayCustomQuickSort1D($avArray, $sSortFunc, $L, $iEnd)
EndFunc ;==>__ArrayCustomQuickSort1D
; #INTERNAL_USE_ONLY#============================================================================================================
; Name...........: __ArrayCustomQuickSort2D
; Description ...: Helper function for sorting 2D arrays
; Syntax.........: __ArrayCustomQuickSort2D(ByRef $avArray, ByRef $sSortFunc, ByRef $iStep, ByRef $iStart, ByRef $iEnd, ByRef $iSubItem, ByRef $iSubMax)
; Parameters ....: $avArray - Array to sort
; $iStep - Step size (should be 1 to sort ascending, -1 to sort descending!)
; $iStart - Index of array to start sorting at
; $iEnd - Index of array to stop sorting at
; $iSubItem - Sub-index to sort on in 2D arrays
; $iSubMax - Maximum sub-index that array has
; Return values .: None
; Author ........: Jos van der Zande, LazyCoder, Tylo, Ultima
; Modified.......: Erik Pilsits - removed IsNumber testing
; Remarks .......: For Internal Use Only
; Related .......:
; Link ..........;
; Example .......;
; ===============================================================================================================================
Func __ArrayCustomQuickSort2D(ByRef $avArray, ByRef $sSortFunc, ByRef $iStep, ByRef $iStart, ByRef $iEnd, ByRef $iSubItem, ByRef $iSubMax)
If $iEnd <= $iStart Then Return
; QuickSort
Local $i, $vTmp, $L = $iStart, $R = $iEnd, $vPivot = $avArray[Int(($iStart + $iEnd) / 2)][$iSubItem]
Do
While ($iStep * Call($sSortFunc, $avArray[$L][$iSubItem], $vPivot) < 0)
$L += 1
WEnd
While ($iStep * Call($sSortFunc, $avArray[$R][$iSubItem], $vPivot) > 0)
$R -= 1
WEnd
; Swap
If $L <= $R Then
For $i = 0 To $iSubMax
$vTmp = $avArray[$L][$i]
$avArray[$L][$i] = $avArray[$R][$i]
$avArray[$R][$i] = $vTmp
Next
$L += 1
$R -= 1
EndIf
Until $L > $R
__ArrayCustomQuickSort2D($avArray, $sSortFunc, $iStep, $iStart, $R, $iSubItem, $iSubMax)
__ArrayCustomQuickSort2D($avArray, $sSortFunc, $iStep, $L, $iEnd, $iSubItem, $iSubMax)
EndFunc ;==>__ArrayCustomQuickSort2D
【讨论】:
以上是关于使用 AutoIt 的用户定义排序比较的主要内容,如果未能解决你的问题,请参考以下文章