Jump to content
Sign in to follow this  
czardas

_ArrayShuffle

Recommended Posts

czardas

Melba has posted an example here:

I don't quite understand the 2D choices. There are several options you might consider:

1. shuffling rows

2. shuffling columns

3. shuffling elements (total 2D chaos)

Edited by czardas

Share this post


Link to post
Share on other sites
Melba23

czardas,

 

I don't quite understand the 2D choices

There is only one - shuffle a column. The idea being that sorting on that column will then shuffle all the rows in the array. :)

There are several options you might consider

I did consider adding other options but decided that was going too far for the standard Array UDF. If anyone needs more complex shuffles then they can always post something in Examples so that any other interested parties could use it. ;)

M23


Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Share this post


Link to post
Share on other sites
czardas

Now I get your concept - thanks for responding. Yes I agree with you about keeping it simple. I created a multidim (up to 11 dimensions) >no-holds-barred version but the code is still a bit messy. :)

Edited by czardas

Share this post


Link to post
Share on other sites
czardas

I was just thinking about this again. If the idea is to have a simple 2D shuffle fuction to cater for beginners, then why not go the whole hog and simplify things even further. The chances of someone wanting to shuffle a single column are less than someone wanting to shuffle a number of rows within the array (according to your idea). To stick with this concept, and cater for the most likely scenario - why not just shuffle the rows within the range. The approach requires less code and should be more efficient than using Fisher–Yates.

;

Func _ArrayShuffle(ByRef $avArray, $iStart_Row = 0, $iEnd_Row = 0)

    If $iStart_Row = Default Then $iStart_Row = 0
    If $iEnd_Row = Default Then $iEnd_Row = 0

    If Not IsArray($avArray) Then Return SetError(1, 0, -1)
    Local $iDim_1 = UBound($avArray, $UBOUND_ROWS)
    If $iEnd_Row = 0 Then $iEnd_Row = $iDim_1 - 1
    If $iStart_Row < 0 Or $iStart_Row > $iDim_1 - 1 Then Return SetError(3, 0, -1)
    If $iEnd_Row < 1 Or $iEnd_Row > $iDim_1 - 1 Then Return SetError(3, 0, -1)
    If $iStart_Row > $iEnd_Row Then Return SetError(4, 0, -1)

    Switch UBound($avArray, $UBOUND_DIMENSIONS)
        Case 1 ; Fisher–Yates algorithm
            Local $vTmp, $iRand
            For $i = $iEnd_Row To $iStart_Row + 1 Step -1
                $iRand = Random($iStart_Row, $i, 1)
                $vTmp = $avArray[$i]
                $avArray[$i] = $avArray[$iRand]
                $avArray[$iRand] = $vTmp
            Next
            Return 1
        Case 2 ; Modified section
            Local $iDim_2 = UBound($avArray, $UBOUND_COLUMNS)
            ReDim $avArray[$iDim_1][$iDim_2 +1]
            For $i = $iStart_Row To $iEnd_Row
                $avArray[$i][$iDim_2] = Random()
            Next

            _ArraySort($avArray, 0, $iStart_Row, $iEnd_Row, $iDim_2)

            ReDim $avArray[$iDim_1][$iDim_2]
            Return 1
        Case Else
            Return SetError(2, 0, -1)
    EndSwitch

EndFunc   ;==>_ArrayShuffle

;

This is just an example. I have not looked into error checks or documentation. I just rewrote the 2D part of the code. Shuffling the elements within a single column is more the exception rather than the rule. My modifications to M23's version have been tested on an older release. Let me know if any of the constants are incorrect and I'll post the code I tested on my machine.

Edited by czardas

Share this post


Link to post
Share on other sites
Melba23

czardas,

As I explained earlier I added the column option to meet a specific request - which was to allow the "index" column of a 2D array to be shuffled and then the array could be sorted on that column which would leave the "index" column in order but with all other columns shuffled. Omitting that parameter shuffles all rows just as with your code :)

But I must say that when I test your suggested code, it is nearly 3 times as slow as the Beta even with the "column" overhead. I used a well-respected shuffle algorithm for a reason. ;)

M23


Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Share this post


Link to post
Share on other sites
czardas

You say it's for a specific request which seems a contradiction to what you said earlier.

If anyone needs more complex shuffles then they can always post something in Examples

 

I can only imagine my code to be slower if your test didn't use Redim and _ArraySort(). Shuffling row indices as an interim process for shuffling rows seems to me to be very specific case. If your array does not have an index column, then you have to add one and later remove it - that's the expected latency I was referring to.

When you want to create a row index shuffle without using Redim, then you should be advanced enough to optimize the process yourself to suit your personal requirements. I ask myself which is preferable, having to add and remove a column or having to overwrite the (out of order) indices within the range?

Edited by czardas

Share this post


Link to post
Share on other sites
Melba23

czardas,

It was not meant to be a contradiction - my earlier comment should perhaps have read "If anyone needs more complex shuffles than are provided in the UDF then they can always post something in Examples". :)

And as I use the new functionality myself I claim "droit d'auteur" for leaving it in. ;)

 

I can only imagine my code to be slower if your test doesn't use Redim

As you can see from the code in the thread where I posted the function, the code does not use ReDim - it uses the same Fisher–Yates algorithm as in the 1D case. You do realise that the UDF will indeed shuffle all rows of a 2D array (giving the same result as your code) and the single column shuffle is only an option? :huh:

M23


Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Share this post


Link to post
Share on other sites
czardas

 it uses the same Fisher–Yates algorithm as in the 1D case. You do realise that the UDF will indeed shuffle all rows of a 2D array (giving the same result as your code) and the single column shuffle is only an option? :huh:

 

Oops, silly me. :> I should have more faith. Ignore everything I said.

Share this post


Link to post
Share on other sites
Melba23

czardas,

Re-reading the thread I suddenly wondered if you had misunderstood the code. No harm done. :)

M23

  • Like 1

Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Share this post


Link to post
Share on other sites
Melba23

czardas,

I would much people asked questions and tried to help improve the code than just sat there and fumed because they thought it was not correct. :)

This will be the Help file entry - I hope it is clear enough that others will not fall into the same trap:

###User Defined Function###
_ArrayShuffle

###Description###
Shuffles selected rows 1D and 2D arrays - can be limited to a specific column in 2D arrays

###Syntax###
#include <Array.au3>
_ArrayShuffle ( ByRef $aArray [, $iStart_Row = 0 [, $iEnd_Row = 0 [, $iCol = 0]]] )


###Parameters###
@@ParamTable@@
$aArray
    Array to modify
$iStart_Row
    [optional] Start row for shuffle - default first
$iEnd_Row
    [optional] End row for shuffle - default last
$iCol
    [optional] Specific column to shuffle (2D only)
@@End@@

###ReturnValue###
@@ReturnTable@@
Success:    1.
Failure:    -1 and sets the @error flag to non-zero.
@error: 1 - $aArray is not an array
    2 - $aArray is not a 1D or 2D array
    3 - $iStart or $iEnd outside array bounds
    4 - $iStart greater than $iEnd
    5 - $iColumn is outside array bounds
@@End@@


###Remarks###
The function uses the Fisher-Yates shuffle algorithm.


###Related###
None.


###Example###
@@IncludeExample@@
Please let me know it you think it is not. ;)

M23


Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Share this post


Link to post
Share on other sites
czardas

The wording is clear and well thought out. For some reason I had it in my head that it was only shuffling a selected column. I got as far as the following line and made an incorrect assumption:

If $iCol = Default Then $iCol = 0

;

Looking again I do see one thing worth mentioning: If I set $iCol = 0, it does not only shuffle the first column. Perhaps this is a bug.

Share this post


Link to post
Share on other sites
Melba23

czardas,

I told you I would rather people spoke out. :D

An easy fix - thanks for spotting it. :)

M23

Edit: And fixed it is. :)

Edited by Melba23

Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Share this post


Link to post
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
Sign in to follow this  

×