Sort, Push, RemoveAt etc., with 2D array/object? Topic is solved

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
ahketype
Posts: 191
Joined: 27 Oct 2016, 15:06
Location: Yorkshire, UK

Sort, Push, RemoveAt etc., with 2D array/object?

Post by ahketype » 27 Jan 2022, 10:39

Can you sort a 2D array on a row (or column), so that all other contents are sorted along with the indexed row? If so, could someone show me the syntax for doing that please? Also, can you use .push() for a whole row/column (say, to add a separate 1D array as a new row/col), and RemoveAt a similar set of data? Can these be done in a single command, or does it need a longer function?

I've read the help file pages on objects and arrays loads of times, but I'm still confused. There are examples of Sort, Push, Pop, Delete, RemoveAt, and so on, for 1D arrays or associative arrays, and then there are some complex examples with combinations of square brackets, curly braces, parentheses and/or dots, but little in between.

In writing the following code as a skeleton to try different things, I finally realised the simple assignment a[x] := temp adds a temp[] 1D array to a[].

The help on Push suggests a parameter can be passed with temp*, but again only in the context of a 1D array, so I'm guessing this can only be used for appending the contents of temp[] linearly to a 1D array.

Starter for you:

Code: Select all

#Warn
#NoEnv
a := [] ; a will be a 2D table
Loop, 3
{
	x := A_Index
	temp := [] ; create/clear temporary 1D array for 'y' dimension
	Loop, 4
	{
		y:= A_Index
		Random, r, 0, 9
		temp.push(r)
		; MsgBox % temp[y]
	}
	a[x] := temp ; This works. Just wondered if there's an equivalent push method
	; like a[x].push(temp), which didn't work
	; and any equivalent pop, delete, removeat, etc.
}
; Main question, is there a way to sort a[] on any chosen row/col?

; Output table
out := ""
Loop, 5
{
	x := A_Index
	Loop, 8
	{
		y:= A_Index
		out .= a[x][y] . " "
	}
	out .= "`n"
}
MsgBox, % out
Cheers

User avatar
mikeyww
Posts: 26588
Joined: 09 Sep 2014, 18:38

Re: Sort, Push, RemoveAt etc., with 2D array/object?

Post by mikeyww » 27 Jan 2022, 10:50

You may want to have a look at bigA.

Code: Select all

a := []
a.1 := []
a[1].Push(4)
MsgBox % a.1.1

User avatar
Chunjee
Posts: 1400
Joined: 18 Apr 2014, 19:05
Contact:

Re: Sort, Push, RemoveAt etc., with 2D array/object?  Topic is solved

Post by Chunjee » 27 Jan 2022, 13:05

The problem with array/object documentation I think stems from the fact that ahk didn't start with arrays. For a long time there were just psudoarrays. I think next array[x][y] became common which you'll see on the archived forums a lot, finally array[index, key] became available and for me that has been the easiest to understand so I recommend that.

If you are getting into arrays I highly recommend https://chunjee.github.io/array.ahk to add common methods; though they are more 1D array centric.


for sorting a 2D arrays you must check out https://biga-ahk.github.io/biga.ahk/#/?id=sortby

Code: Select all

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

array := [[4, 2, 0, 6], [7, 4, 1, 2], [2, 1, 4, 5]]
; sort by the first element of each array
sortedArray := A.sortBy(array, 1)
; => [[2, 1, 4, 5], [4, 2, 0, 6], [7, 4, 1, 2]]

ahketype
Posts: 191
Joined: 27 Oct 2016, 15:06
Location: Yorkshire, UK

Re: Sort, Push, RemoveAt etc., with 2D array/object?

Post by ahketype » 27 Jan 2022, 18:42

Thanks guys,

@Chunjee Thanks, it was good to see the example with nested (2D) array elements, and to understand a bit more about where my confusion comes from, i.e. the history of array development in AHK.

I might use that sortBy() function, or I might just see if I can cobble something together - sometimes it's good to go back to first principles. I could write a routine to recursively find each next value in the sort, and then use its ID to shuffle elements in all the array, or create a new one as I go. It would save having all the library installed for just that one function. I also confess I have no idea how to get and install the damn thing from github if I wanted to. :mrgreen: Or I might revert to separate arrays and do that. It would be a lot easier. Every time I've tried to use objects like this in AHK I revert to separate arrays.

Thanks @mikeyww for that little chunk of code, which made me realise something about the syntax of nested arrays, and allowed me to write a pop() and removeat() on the end of this example. I'm still figuring it out. I'm used to a very different syntax in another language.

Code: Select all

#Warn
#NoEnv
a := [] ; a will be a 2D table
Loop, 3
{
	x := A_Index
	temp := [] ; create/clear temporary 1D array for 'y' dimension
	Loop, 4
	{
		y:= A_Index
		Random, r, 0, 9
		temp.push(r)
		; MsgBox % temp[y]
	}
	a[x] := temp ; This works. Just wondered if there's an equivalent push method
	; like a[x].push(temp), which didn't work
	; and any equivalent pop, delete, removeat, etc.
}
; Main question, is there a way to sort a[] on any chosen row/col?

; Output table
out := ""
Loop, 5
{
	x := A_Index
	Loop, 8
	{
		y:= A_Index
		out .= a[x][y] . " "
	}
	out .= "`n"
}

MsgBox, % out

; pop last row off a and msg it.
b := a.pop()
MsgBox % b[1] b[2] b[3] b[4]

;removeat first row and show that.
c := a.removeat(1)
MsgBox % c[1] c[2] c[3] c[4]

; how many rows left in a?
MsgBox, % a.MaxIndex()

ahketype
Posts: 191
Joined: 27 Oct 2016, 15:06
Location: Yorkshire, UK

Re: Sort, Push, RemoveAt etc., with 2D array/object?

Post by ahketype » 27 Jan 2022, 18:57

Oh, and my mistake on push() was trying a[x].push(temp) when it should have just been a.push(temp). Hell it's confusing. So I was maybe trying to push temp into an element of a[x] rather than of a, without that depth having been dimensioned? Which (if I wanted to) would require something like a.x := [] first. :think:

User avatar
mikeyww
Posts: 26588
Joined: 09 Sep 2014, 18:38

Re: Sort, Push, RemoveAt etc., with 2D array/object?

Post by mikeyww » 27 Jan 2022, 19:27

Yes, that can be tricky at times. You might find Arrays of Arrays to be an informative passage. Enjoy!

ahketype
Posts: 191
Joined: 27 Oct 2016, 15:06
Location: Yorkshire, UK

Re: Sort, Push, RemoveAt etc., with 2D array/object?

Post by ahketype » 28 Jan 2022, 18:32

mikeyww wrote:
27 Jan 2022, 19:27
Yes, that can be tricky at times. You might find Arrays of Arrays to be an informative passage. Enjoy!
Yes, I've read it many times, but apparently too quickly! It's pretty dense. I should unpack it and do some experiments.

I've written a sort routine that does what I wanted, so here it is in case anyone finds it useful:

Code: Select all

; Sort array elements (rows) on value of particular element (column) of nested arrays
#Warn
#NoEnv
; Make following max vars the dimension of the 2D table for testing...
maxx := 10
maxy := 15

a := [] ; a will be a 2D table

; Build table
Loop, % maxy
{
	temp := [] ; create/clear temporary 1D array for 'x' dimension
	Loop, % maxx
	{
		Random, r, 0, 999
		temp.push(r)
	}
	a.push(temp)
}

; Display and sort array
Loop
	gosub, sortCol
until ErrorLevel
Exit

sortCol:
; Format array into table...
out := ""
Loop, % maxy
{
	x := A_Index
	Loop, % maxx
	{
		out .= a[x][A_Index] . A_Tab
	}
	out .= "`n"
}
; show, and choose which column to sort on
getCol:
InputBox, n, , % out "`nChoose a column to sort array on", , 600, 400
if ((n < 1) or (n > maxx)) and !ErrorLevel
	goto, getCol
; Sort array in column n order
b := [] ; temporary array for swapping elements
Loop
{
	Loop, % a.MaxIndex() ; Go through array
	{
		switch := false ; flag so we know when all done
		start := A_Index
		this := a[start][n] ; nth element in a[start] nested array
		Loop, % a.MaxIndex() - start ; loop from start onwards
		{
			another := A_Index + start
			tocompare := a[another][n] ; nth element of array to compare
			if (tocompare < this) ; reverse this to give reverse order
			{
				b := a[start] ; do the swap
				a[start] := a[another] ; no InsertAt() is needed
				a[another] := b ; just re-assignment of the element
				switch := true ; something needed switching, so something else may on next pass
				break, 2 ; restart scan
			}
		}
	}
} until !switch ; full scan, no switches done = finished
return

Post Reply

Return to “Ask for Help (v1)”