Sorting Array by Length Topic is solved

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
HeXaDeCiMaToR
Posts: 155
Joined: 08 Feb 2021, 12:42

Sorting Array by Length

20 Apr 2021, 12:12

I've got 1000+ items in an array that I need to be sorted by the length of each item (spaces, /, -, . counted as well). The only forum or documentation that I can find counts up to the first space and then moves to the next item. My delimiter is a pipe.

Help! :headwall:
User avatar
mikeyww
Posts: 26871
Joined: 09 Sep 2014, 18:38

Re: Sorting Array by Length

20 Apr 2021, 12:54

Code: Select all

strings := ["def", "defabc", "ae", "ad"], str := ""
For index, string in strings
 str .= (A_Index = 1 ? "" : "`n") StrLen(string) "`t" string
Sort, str, N
strings := []
For lineNum, line in StrSplit(str, "`n")
 strings.Push(RegExReplace(line, ".+\t"))
User avatar
rommmcek
Posts: 1473
Joined: 15 Aug 2014, 15:18

Re: Sorting Array by Length

21 Apr 2021, 05:36

HeXaDeCiMaToR wrote:
20 Apr 2021, 12:12
I've got 1000+ items in an array... My delimiter is a pipe.
Edit: Updated the reference!
??? Can you post your array w/ such delimiter...
Last edited by rommmcek on 21 Apr 2021, 09:21, edited 2 times in total.
User avatar
Chunjee
Posts: 1418
Joined: 18 Apr 2014, 19:05
Contact:

Re: Sorting Array by Length

21 Apr 2021, 13:30

This proved to be quite an interesting challenge but I think I got it :idea:

Code: Select all

A := new biga() ; requires https://www.npmjs.com/package/biga.ahk

strings := StrSplit("def|defabc|ae|ad", "|")
A.sortBy(strings, A.size)
; => ["ad", "ae", "def", "defabc"]

Since StrLen() will also return the length of a string this works too:

Code: Select all

A.sortBy(strings, StrLen)
; => ["ad", "ae", "def", "defabc"]
https://biga-ahk.github.io/biga.ahk/#/?id=sortby
HeXaDeCiMaToR
Posts: 155
Joined: 08 Feb 2021, 12:42

Re: Sorting Array by Length

21 Apr 2021, 13:59

@rommmcek You make a good point. I have a string (with pipes) that I convert to an array (replace "|", ", "). I want to use the string because it throws up fewer "expression is too long" errors.

HOWEVER, I think I've solved it by just going straight to API on this project. Oddly enough it was easier to learn API than it was to figure out how to sort by length lol

I'm going to check out that pack though!!
User avatar
Xtra
Posts: 2750
Joined: 02 Oct 2015, 12:15

Re: Sorting Array by Length

21 Apr 2021, 14:45

Example that will keep order of same lengths from min to max index.

Code: Select all

arr := ["abc", "98765", "pc", "I", "autohotkey", "ahk", "98764"]

SortArrByLen(arr)

for key, val in arr
    MsgBox, 4096, % key, % val
ExitApp

SortArrByLen(ByRef arr) {
    arrGroups := [], cnt := 0
    for i, str in arr
    {
        if !IsObject(arrGroups[n := StrLen(str)])
            arrGroups[n] := []
        arrGroups[n].push(str)
    }
    for i, group in arrGroups
        for j, string in group
            arr[++cnt] := string
}
HeXaDeCiMaToR
Posts: 155
Joined: 08 Feb 2021, 12:42

Re: Sorting Array by Length

21 Apr 2021, 15:02

@Xtra would that be difficult to put Descending Sort (Max to Min)?
User avatar
Xtra
Posts: 2750
Joined: 02 Oct 2015, 12:15

Re: Sorting Array by Length  Topic is solved

21 Apr 2021, 15:12

Sure no problem:

Code: Select all

arr := ["abc", "98765", "pc", "I", "autohotkey", "ahk", "98764"]

SortArrByLen(arr)

for key, val in arr
    MsgBox, 4096, % key, % val
ExitApp

SortArrByLen(ByRef arr) {
    arrGroups := [], cnt := 0
    for i, str in arr
    {
        if !IsObject(arrGroups[n := StrLen(str)])
            arrGroups[n] := []
        arrGroups[n].InsertAt(1,str)
    }
    for i, group in arrGroups
        for j, string in group
            arr[++cnt] := string
}
User avatar
mikeyww
Posts: 26871
Joined: 09 Sep 2014, 18:38

Re: Sorting Array by Length

21 Apr 2021, 15:18

Clever technique!
User avatar
rommmcek
Posts: 1473
Joined: 15 Aug 2014, 15:18

Re: Sorting Array by Length

21 Apr 2021, 16:28

Here are the roots of the Clever technique.
To reverse sorting use better negative index length. InssertAt(1, str) is utterly slow.

Code: Select all

	;...
        if !IsObject(arrGroups[-n := StrLen(str)])
            arrGroups[-n] := []
        arrGroups[-n].push(str)
        ;...
Edit: Fixing typo (minus sign), thanks to Xtra.
For large data however array assisted sorting is preferable!
Last edited by rommmcek on 21 Apr 2021, 19:33, edited 1 time in total.
User avatar
Xtra
Posts: 2750
Joined: 02 Oct 2015, 12:15

Re: Sorting Array by Length

21 Apr 2021, 17:20

rommmcek wrote:
21 Apr 2021, 16:28
Here are the roots of the Clever technique.
To reverse sorting use better negative index length. InssertAt(1, str) is utterly slow.

Code: Select all

	;...
        if !IsObject(arrGroups[n := StrLen(str)])
            arrGroups[-n] := []
        arrGroups[-n].push(str)
        ;...
For large data however array assisted sorting is preferable!
What i posted groups the string lengths. It kept the original array order for each group from min to max index.
The 2nd post just reverses the group index order (max to min) not the over all order.

To reverse the over all order you missed checking for a negative key/index using what you posted does not work correctly.

Code: Select all

        if !IsObject(arrGroups[-n := StrLen(str)])    ; - missing
            arrGroups[-n] := []
        arrGroups[-n].push(str)
Your last link for "array assisted sorting" is nothing but sorting with vars / pseudo arrays and returning an array via strsplit().
That is why its faster.

HTH
User avatar
rommmcek
Posts: 1473
Joined: 15 Aug 2014, 15:18

Re: Sorting Array by Length

21 Apr 2021, 19:36

Thanks, updated previous post.

P.s.: Array assisted: I thought it's branch prediction and less work due to skipping the saving.
HeXaDeCiMaToR
Posts: 155
Joined: 08 Feb 2021, 12:42

Re: Sorting Array by Length

22 Apr 2021, 05:44

That's good stuff!! Thank you!

However, I'm still getting "Expression too long" errors when trying to do anything with the hardcoded array. I have no issues when I pull it straight from the site and work with that HTTP_Result. But take HTTP_Result (JSON) and paste it into a script to play around with it and AHK yells at me "Expression too long".

@tidbit talks about storing the "array" as a text variable and then using Loop/Parse/StrSplit to split it up into the array. Does that mean split it up into 256 (?keys/tokens/items?)?

https://www.autohotkey.com/boards/viewtopic.php?t=28288

I've never used Parse or StrSplit before. So, I'll read up on it and let you know what I "figure out" :crazy:

UPDATE: I thought I'd give you the Array to look at...

Code: Select all

MakesArray := {"Acura":"m4"},{"Alfa Romeo":"m124"},{"Audi":"m19"},{"BMW":"m3"},{"Buick":"m21"},{"Cadillac":"m22"},{"Chevrolet":"m1"},{"Chrysler":"m23"},{"Dodge":"m24"},{"FIAT":"m98"},{"Ford":"m2"},{"Genesis":"m203"},{"GMC":"m26"},{"Honda":"m6"},{"Hyundai":"m28"},{"INFINITI":"m84"},{"Jaguar":"m31"},{"Jeep":"m32"},{"Kia":"m33"},{"Land Rover":"m35"},{"Lexus":"m37"},{"Lincoln":"m38"},{"Maserati":"m40"},{"Mazda":"m42"},{"Mercedes-Benz":"m43"},{"MINI":"m45"},{"Mitsubishi":"m46"},{"Nissan":"m12"},{"Pontiac":"m47"},{"Porsche":"m48"},{"RAM":"m191"},{"Scion":"m52"},{"Subaru":"m53"},{"Toyota":"m7"},{"Volkswagen":"m55"},{"Volvo":"m56"},{"Acura":"m4"},{"Alfa Romeo":"m124"},{"AM General":"m79"},{"AMC":"m133"},{"Ariel":"m128"},{"Aston Martin":"m110"},{"Audi":"m19"},{"Austin":"m119"},{"Austin-Healey":"m139"},{"Autobianchi":"m234"},{"Bentley":"m20"},{"BMW":"m3"},{"Bricklin":"m196"},{"Bugatti":"m113"},{"Buick":"m21"},{"Cadillac":"m22"},{"Chevrolet":"m1"},{"Chrysler":"m23"},{"Citroen":"m117"},{"Cord":"m215"},{"Daewoo":"m81"},{"Datsun":"m96"},{"De Tomaso":"m179"},{"DeLorean":"m97"},{"DeSoto":"m208"},{"Dodge":"m24"},{"Eagle":"m82"},{"Edsel":"m174"},{"Excalibur":"m198"},{"Ferrari":"m25"},{"FIAT":"m98"},{"Fisker":"m183"},{"Ford":"m2"},{"Franklin":"m216"},{"Freightliner":"m99"},{"Genesis":"m203"},{"Geo":"m83"},{"GMC":"m26"},{"Graham":"m247"},{"Hillman":"m144"},{"Honda":"m6"},{"Hudson":"m186"},{"Hummer":"m27"},{"Hyundai":"m28"},{"INFINITI":"m84"},{"International Harvester":"m158"},{"Isuzu":"m30"},{"Jaguar":"m31"},{"Jeep":"m32"},{"Jensen":"m200"},{"Kaiser":"m189"},{"Karma":"m233"},{"Kia":"m33"},{"Lamborghini":"m34"},{"Lancia":"m100"},{"Land Rover":"m35"},{"Lexus":"m37"},{"Lincoln":"m38"},{"Lotus":"m39"},{"Maserati":"m40"},{"Maybach":"m41"},{"Mazda":"m42"},{"McLaren":"m141"},{"Mercedes-Benz":"m43"},{"Mercury":"m44"},{"Messerschmitt":"m219"},{"MG":"m102"},{"MINI":"m45"},{"Mitsubishi":"m46"},{"Mobility Ventures":"m255"},{"Morgan":"m150"},{"Morris":"m151"},{"Moskvitch":"m154"},{"Muntz":"m268"},{"Nash":"m199"},{"Nissan":"m12"},{"Oldsmobile":"m85"},{"Opel":"m103"},{"Packard":"m176"},{"Pagani":"m121"},{"Panoz":"m86"},{"Peugeot":"m104"},{"Pininfarina":"m105"},{"Plymouth":"m87"},{"Polestar":"m260"},{"Pontiac":"m47"},{"Porsche":"m48"},{"RAM":"m191"},{"Riley":"m267"},{"Rolls-Royce":"m49"},{"Rover":"m131"},{"Saab":"m50"},{"Saturn":"m51"},{"Scion":"m52"},{"Shelby":"m135"},{"smart":"m111"},{"SRT":"m194"},{"Studebaker":"m164"},{"Subaru":"m53"},{"Sunbeam":"m132"},{"Suzuki":"m54"},{"Tesla":"m112"},{"Toyota":"m7"},{"Triumph":"m137"},{"Volkswagen":"m55"},{"Volvo":"m56"},{"VPG":"m205"},{"Willys":"m214"}
HeXaDeCiMaToR
Posts: 155
Joined: 08 Feb 2021, 12:42

Re: Sorting Array by Length

22 Apr 2021, 06:20

I modified the array and now it's finally giving me results, but it's only returning "key" and not "value"...

Any thoughts?

Code: Select all

MakesArray := {"Acura":"m4","Alfa Romeo":"m124","Audi":"m19","BMW":"m3","Buick":"m21","Cadillac":"m22","Chevrolet":"m1","Chrysler":"m23","Dodge":"m24","FIAT":"m98","Ford":"m2","Genesis":"m203","GMC":"m26","Honda":"m6","Hyundai":"m28","INFINITI":"m84","Jaguar":"m31","Jeep":"m32","Kia":"m33","Land Rover":"m35","Lexus":"m37","Lincoln":"m38","Maserati":"m40","Mazda":"m42","Mercedes-Benz":"m43","MINI":"m45","Mitsubishi":"m46","Nissan":"m12","Pontiac":"m47","Porsche":"m48","RAM":"m191","Scion":"m52","Subaru":"m53","Toyota":"m7","Volkswagen":"m55","Volvo":"m56","Acura":"m4","Alfa Romeo":"m124","Aston Martin":"m110","Audi":"m19","Austin":"m119","Bentley":"m20","BMW":"m3","Buick":"m21","Cadillac":"m22","Chevrolet":"m1","Chrysler":"m23","Datsun":"m96","DeLorean":"m97","Dodge":"m24","Eagle":"m82","Excalibur":"m198","Ferrari":"m25","FIAT":"m98","Ford":"m2","Freightliner":"m99","Genesis":"m203","Geo":"m83","GMC":"m26","Graham":"m247","Honda":"m6","Hudson":"m186","Hummer":"m27","Hyundai":"m28","INFINITI":"m84","Isuzu":"m30","Jaguar":"m31","Jeep":"m32","Kia":"m33","Lamborghini":"m34","Land Rover":"m35","Lexus":"m37","Lincoln":"m38","Lotus":"m39","Maserati":"m40","Maybach":"m41","Mazda":"m42","McLaren":"m141","Mercedes-Benz":"m43","Mercury":"m44","MG":"m102","MINI":"m45","Mitsubishi":"m46","Mobility Ventures":"m255","Nissan":"m12","Oldsmobile":"m85","Plymouth":"m87","Pontiac":"m47","Porsche":"m48","RAM":"m191","Rolls-Royce":"m49","Rover":"m131","Saab":"m50","Saturn":"m51","Scion":"m52","Shelby":"m135","smart":"m111","SRT":"m194","Studebaker":"m164","Subaru":"m53","Sunbeam":"m132","Suzuki":"m54","Tesla":"m112","Toyota":"m7","Triumph":"m137","Volkswagen":"m55","Volvo":"m56"}




for key, vaule in MakesArray
	MsgBox %key% = %value%
UPDATE: TYPO "vaule"
User avatar
rommmcek
Posts: 1473
Joined: 15 Aug 2014, 15:18

Re: Sorting Array by Length

22 Apr 2021, 08:34

Code: Select all

MakesArray := {"Acura":"m4","Alfa Romeo":"m124","Audi":"m19","BMW":"m3","Buick":"m21","Cadillac":"m22","Chevrolet":"m1","Chrysler":"m23","Dodge":"m24","FIAT":"m98","Ford":"m2","Genesis":"m203","GMC":"m26","Honda":"m6","Hyundai":"m28","INFINITI":"m84","Jaguar":"m31","Jeep":"m32","Kia":"m33","Land Rover":"m35","Lexus":"m37","Lincoln":"m38","Maserati":"m40","Mazda":"m42","Mercedes-Benz":"m43","MINI":"m45","Mitsubishi":"m46","Nissan":"m12","Pontiac":"m47","Porsche":"m48","RAM":"m191","Scion":"m52","Subaru":"m53","Toyota":"m7","Volkswagen":"m55","Volvo":"m56","Acura":"m4","Alfa Romeo":"m124","Aston Martin":"m110","Audi":"m19","Austin":"m119","Bentley":"m20","BMW":"m3","Buick":"m21","Cadillac":"m22","Chevrolet":"m1","Chrysler":"m23","Datsun":"m96","DeLorean":"m97","Dodge":"m24","Eagle":"m82","Excalibur":"m198","Ferrari":"m25","FIAT":"m98","Ford":"m2","Freightliner":"m99","Genesis":"m203","Geo":"m83","GMC":"m26","Graham":"m247","Honda":"m6","Hudson":"m186","Hummer":"m27","Hyundai":"m28","INFINITI":"m84","Isuzu":"m30","Jaguar":"m31","Jeep":"m32","Kia":"m33","Lamborghini":"m34","Land Rover":"m35","Lexus":"m37","Lincoln":"m38","Lotus":"m39","Maserati":"m40","Maybach":"m41","Mazda":"m42","McLaren":"m141","Mercedes-Benz":"m43","Mercury":"m44","MG":"m102","MINI":"m45","Mitsubishi":"m46","Mobility Ventures":"m255","Nissan":"m12","Oldsmobile":"m85","Plymouth":"m87","Pontiac":"m47","Porsche":"m48","RAM":"m191","Rolls-Royce":"m49","Rover":"m131","Saab":"m50","Saturn":"m51","Scion":"m52","Shelby":"m135","smart":"m111","SRT":"m194","Studebaker":"m164","Subaru":"m53","Sunbeam":"m132","Suzuki":"m54","Tesla":"m112","Toyota":"m7","Triumph":"m137","Volkswagen":"m55","Volvo":"m56"}

;pa(MakesArray)
for key, value in MakesArray
	MsgBox % key " = " value ; MakesArray[key]
    
Esc:: ExitApp

pa(in) {
    MsgBox % txtArr(in)
}

txtArr(r, i:="  ", d:=0, b:="") {
	For k, v in (r, IsObject(r)? "": e:= 1)
		c.= IsObject(v)? b k ":`n" txtArr(v, i, d+1, b i): b k ": " v "`n", d>0? "": t:=c
    Return e? r: d>0? c: t
}
What is your original data and what do you want is your final goal?
Last edited by rommmcek on 22 Apr 2021, 21:38, edited 1 time in total.
User avatar
boiler
Posts: 16912
Joined: 21 Dec 2014, 02:44

Re: Sorting Array by Length

22 Apr 2021, 09:27

Why do this:
rommmcek wrote:

Code: Select all

for key, vaule in MakesArray
	MsgBox % key " = " MakesArray[key]
...instead of:

Code: Select all

for key, value in MakesArray
	MsgBox % key " = " value
That's basically the rasion d'etre for the for loop. As @HeXaDeCiMaToR noted, his issue was a typo (value/vaule).
User avatar
rommmcek
Posts: 1473
Joined: 15 Aug 2014, 15:18

Re: Sorting Array by Length

22 Apr 2021, 21:37

Thanks, I flatly overlooked both, his typo and update.
HeXaDeCiMaToR
Posts: 155
Joined: 08 Feb 2021, 12:42

Re: Sorting Array by Length

22 Apr 2021, 22:34

How about this........

In JSON I've got an array within an array "models":[{"Cars":[{"ALL YEARS AVAILABLE"}],"id":"IT's VALUE"}. I've been able to navigate inside one nested array, but I can't seem to get the value for "id" on this one.

Code: Select all

{"models":[{"cars":[{"year":2004,"id":"c3881"},{"year":2003,"id":"c3883"},{"year":2002,"id":"c3885"},{"year":2001,"id":"c3893"},{"year":2000,"id":"c3896"},{"year":1999,"id":"c3901"},{"year":1998,"id":"c3905"},{"year":1997,"id":"c3909"},{"year":1996,"id":"c3914"},{"year":1995,"id":"c3918"},{"year":1994,"id":"c3922"},{"year":1992,"id":"c3932"},{"year":1991,"id":"c3938"},{"year":1990,"id":"c3944"},{"year":1988,"id":"c4436"},{"year":1987,"id":"c4435"},{"year":1984,"id":"c4432"}],"id":"d628"},{"cars":[{"year":2000,"id":"c3894"},{"year":1999,"id":"c3899"},{"year":1998,"id":"c3903"},{"year":1997,"id":"c3907"},{"year":1996,"id":"c3911"},{"year":1995,"id":"c3916"},{"year":1994,"id":"c3920"},{"year":1993,"id":"c3925"},{"year":1992,"id":"c3930"},{"year":1991,"id":"c3935"},{"year":1990,"id":"c3941"},{"year":1989,"id":"c16531"},{"year":1988,"id":"c16530"}],"id":"d752"}
I've tried

Code: Select all

values := Response_Text
values := JSON.Load(values)
; Model := values.models.id
; Model := values.models[1].id
; Model := values.models.id[1]
; Model := values.models[1].id[1]
as this has worked in the past on another JSON

Code: Select all

jsonstr := Response_Text
values := JSON.Load(jsonstr)
Trim1 := values.listings[Num].trimName
This returns "models: " in the msgbox.

Code: Select all

for key, value in values
MsgBox % key ": " values
I just can't get to the "id"

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: No registered users and 327 guests