Champak Posted September 3, 2023 Share Posted September 3, 2023 (edited) I need a multiD array sorted a very specific way that...I don't think....can be achieved a "normal" way and instead would need a reference to sort it. What I'm imagining is set up a reference array with things sorted in the way that I want, and then the array that needs to be sorted looks at that and sorts it's contents in the same manner, skipping anything that it doesn't contain. Is this type of sorting possible? I tried searching custom sort and reference sort. Ex I'm sorting sizes so I'll have, 3-6M, 3-9M, 2T, 2, 3, 3T, 12M, 12, 12-18M, 3 US, 4 US, 12 US and I would need it sorted as 3-6M, 3-9M, 12M, 12-18M, 2, 2T, 3, 3T, 12, 3 US, 4 US, 12 US If a "reference sort" is not possible, how can I go about getting this done? Off the top of my head the only way I can imagine is looping through the reference with a search and copying that row to a new array until I rebuild it in the order that I want. Thanks Edited September 3, 2023 by Champak Link to comment Share on other sites More sharing options...
Andreik Posted September 3, 2023 Share Posted September 3, 2023 Maybe a SQLite table? When the words fail... music speaks. Link to comment Share on other sites More sharing options...
ioa747 Posted September 3, 2023 Share Posted September 3, 2023 add a new column to the table and add a sort number I know that I know nothing Link to comment Share on other sites More sharing options...
Nine Posted September 3, 2023 Share Posted September 3, 2023 Lets first start to understand your sort. Why 3 comes after 3-6M ? Could you elaborate on the rules of sorting so we can provide rightful solution ? “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Screen Scraping Multi-Threading Made Easy Link to comment Share on other sites More sharing options...
mistersquirrle Posted September 4, 2023 Share Posted September 4, 2023 You may want to check out @Melba23's ArrayMultiColSort UDF, it gives a bit more control over sorting, and you can sort by different columns, so you could separate the suffixes (M, T, US) and sort by that column, then the numbers. There's also the ability to set the sort order with strings, though I haven't used this functionality so I can't really guide on it. From the documentation: "Sort order can be either numeric (0/1 = ascending/descending) or a ordered string of items" Besides that, I think maybe an example script/data that we could see would be helpful. We ought not to misbehave, but we should look as though we could. Link to comment Share on other sites More sharing options...
AspirinJunkie Posted September 4, 2023 Share Posted September 4, 2023 I'm just shamelessly advertising: With >>this UDF<< you can use a completely arbitrary comparison function for sorting (and other tasks). In this way you are completely free how data should be sorted. You can write your own algorithm, just as you can use a fixed comparison array. So the whole magic is not in the sorting, but in the greater than/smaller than/equal to comparison of values. Your example from above, for example, is how I would have implemented it: #include "ArrayPlus.au3" ; the array to be sorted Global $aArray[] = ["3-6M", "3-9M", "2T", "2", "3", "3T", "12M", "12", "12-18M", "3 US", "4 US", "12 US" ] ; sort with own comparison function _ArraySortFlexible($aArray, _myRefCompare) ; print the result _ArrayDisplay($aArray, "the sorted array") ; user defined function to compare 2 values for smaller, equal, less Func _myRefCompare($A, $B) ; the reference Local Static $aRefSort[] = ["3-6M", "3-9M", "12M", "12-18M", "2", "2T", "3", "3T", "12", "3 US", "4 US", "12 US"] ; check if the current elements occur in the reference array. For $i = 0 To UBound($aRefSort) - 1 If $A = $aRefSort[$i] Then Return -1 If $B = $aRefSort[$i] Then Return 1 Next ; if both values do not appear in the reference array, use natural sorting. Return __ap_cb_comp_Natural($A, $B) EndFunc But of course 2D arrays work too (more dimensions don't work): Spoiler #include "ArrayPlus.au3" ; the array to be sorted Global $aArray[][] = [["3-6M", 1, 2, 3], ["3-9M", 1, 2, 3], ["2T", 1, 2, 3], ["2", 1, 2, 3], ["3", 1, 2, 3], ["3T", 1, 2, 3], ["12M", 1, 2, 3], ["12", 1, 2, 3], ["12-18M", 1, 2, 3], ["3 US", 1, 2, 3], ["4 US", 1, 2, 3], ["12 US", 1,2,3]] ; sort with user-defined comparison function _ArraySortFlexible($aArray, _myRefCompare) ; print the result _ArrayDisplay($aArray, "the sorted array") ; user defined function to compare 2 values for smaller, equal, less Func _myRefCompare($A, $B) ; the reference Local Static $aRefSort[] = ["3-6M", "3-9M", "12M", "12-18M", "2", "2T", "3", "3T", "12", "3 US", "4 US", "12 US"] ; check if the current elements occur in the reference array. For $i = 0 To UBound($aRefSort) - 1 If $A[0] = $aRefSort[$i] Then Return -1 If $B[0] = $aRefSort[$i] Then Return 1 Next ; if both values do not appear in the reference array, use natural sorting. Return __ap_cb_comp_Natural($A[0], $B[0]) EndFunc Link to comment Share on other sites More sharing options...
Andreik Posted September 4, 2023 Share Posted September 4, 2023 Here is a SQLite approach but @Nine's question is still valid. #include <Array.au3> #include <SQLite.au3> Local $aSizes = ['3-6M', '3-9M', '2T', '2', '3', '3T', '12M', '12', '12-18M', '3 US', '4 US', '12 US'] $aSorted = SortSizes($aSizes) _ArrayDisplay($aSorted) Func SortSizes(ByRef $aSizes) Local $hDB, $N1, $N2, $Alpha _SQLite_Startup() $hDB = _SQLite_Open() _SQLite_Exec($hDB, 'CREATE TABLE Sizes(N1 INT, N2 INT, ALPHA VARCHAR(4));') For $Index = 0 To UBound($aSizes) - 1 $N1 = StringRegExp($aSizes[$Index], '\G\d+', 3) $N1 = IsArray($N1) ? Number($N1[0]) : 0 $N2 = StringRegExp($aSizes[$Index], '\d+\-\K\d+', 3) $N2 = IsArray($N2) ? Number($N2[0]) : 0 $Alpha = StringRegExp($aSizes[$Index], '[a-zA-Z]+', 3) $Alpha = IsArray($Alpha) ? $Alpha[0] : '' _SQLite_Exec($hDB, 'INSERT INTO Sizes(N1, N2, ALPHA)' & _ 'VALUES(NULLIF(' & $N1 & ', 0), NULLIF(' & $N2 & ', 0),' & _SQLite_FastEscape($Alpha) & ');') Next Local $aResult, $iRows, $iCols _SQLite_GetTable2D($hDB, _ 'SELECT N1 || (CASE WHEN N2 IS NULL THEN "" ELSE "-" END) || COALESCE(N2, "") || " " || ALPHA AS Result ' & _ 'FROM Sizes ORDER BY ALPHA, N1, N2;', $aResult, $iRows, $iCols) _SQLite_Close($hDB) _SQLite_Shutdown() _ArrayDelete($aResult, 0) Return $aResult EndFunc When the words fail... music speaks. Link to comment Share on other sites More sharing options...
Moderators Solution Melba23 Posted September 4, 2023 Moderators Solution Share Posted September 4, 2023 Champak, mistersquirrle kindly pointed at my UDF - here it is in action: #include <Array.au3> #include "ArrayMultiColSort.au3" ; Set required sort list $sList = "3-6M,3-9M,12M,12-18M,2,2T,3,3T,12,3 US,4 US,12 US" ; Get an array $aList = StringSplit($sList, ",", 2) ; Shuffle it _ArrayShuffle($aList) ; Make 2D (min required) _ArrayColInsert ($aList, 1) ; And here is the result _ArrayDisplay($aList, "Shuffled", Default, 8) ; Set list in correct format for the UDF Global $aSortData[][] = [[0, $sList]] ; Sort the array using the required sort date _ArrayMultiColSort($aList, $aSortData) ; And here it is _ArrayDisplay($aList, "Sorted", Default, 8) Good enough? M23 Champak and mikell 1 1 Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind Open spoiler to see my UDFs: Spoiler ArrayMultiColSort ---- Sort arrays on multiple columnsChooseFileFolder ---- Single and multiple selections from specified path treeview listingDate_Time_Convert -- Easily convert date/time formats, including the language usedExtMsgBox --------- A highly customisable replacement for MsgBoxGUIExtender -------- Extend and retract multiple sections within a GUIGUIFrame ---------- Subdivide GUIs into many adjustable framesGUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView itemsGUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeViewMarquee ----------- Scrolling tickertape GUIsNoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxesNotify ------------- Small notifications on the edge of the displayScrollbars ----------Automatically sized scrollbars with a single commandStringSize ---------- Automatically size controls to fit textToast -------------- Small GUIs which pop out of the notification area Link to comment Share on other sites More sharing options...
mikell Posted September 4, 2023 Share Posted September 4, 2023 (edited) My 2 cents, using regex to make a template (could be easily adapted) Edit Nine is right. This one is based on the rule : "M" types first, then "digit" or "digit-T" types, then " US" types #Include <Array.au3> Local $arr[12] = ["3-6M", "3-9M", "2T", "2", "3", "3T", "12M", "12", "12-18M", "3 US", "4 US", "12 US"] ; to get : 3-6M, 3-9M, 12M, 12-18M, 2, 2T, 3, 3T, 12, 3 US, 4 US, 12 US _ArrayColInsert ($arr, 1) For $i = 0 to UBound($arr)-1 If StringRegExp($arr[$i][0], '^[\d-]+M$') Then _ $arr[$i][1] = StringFormat("%06i", Number(StringReplace($arr[$i][0], "-", "."))*100) If StringRegExp($arr[$i][0], '^\d+$') Then _ $arr[$i][1] = StringFormat("%06i", Number($arr[$i][0] & "0")*100) If StringRegExp($arr[$i][0], '^\d+T$') Then _ $arr[$i][1] = StringFormat("%06i", Number(StringReplace($arr[$i][0], 'T', "1"))*100) If StringRegExp($arr[$i][0], '^\d+ US$') Then _ $arr[$i][1] = StringFormat("%06i", Number(StringReplace($arr[$i][0], ' US', "00"))*100) Next ;_ArrayDisplay($arr) _ArraySort($arr, 0, 0, 0, 1) _ArrayColDelete($arr, 1, True) _ArrayDisplay($arr) Edited September 4, 2023 by mikell Link to comment Share on other sites More sharing options...
Champak Posted September 4, 2023 Author Share Posted September 4, 2023 (edited) Thanks all of you. I'm going to try all of them out. These are children's clothing. Things with "M" are months (infants, babies), sizes without a letter or "T" are toddlers and young children, sizes with US are shoes. So let's say I were to just order all the 3s, it would go "NB, 0-3M, 3M, 3-6M, 3-9M, 3, 3T, 3 US". The specific order makes it easy to find what is needed. Edited September 4, 2023 by Champak Link to comment Share on other sites More sharing options...
Champak Posted September 11, 2023 Author Share Posted September 11, 2023 Thanks all again, I decided to go with Melba's since it would be much easier to adjust...and understand what I'm adjusting...if I need to change things. Seems like the core of my app is made of Melba's UDFs lol. Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now