# Array and loop

## Recommended Posts

Hello guys,

I have 2D array with string and numbers. For every group of string ( AAAA BBB CC ) i need to get the lowest number, one for group, everything in one loop since in that loop i do other things. In case there are 2 equal min numbers take the first come.

My attempt

```#include <Array.au3>

Local \$aArray[11][3] = [["A", 2, 0],["A", 3, 0],["A", 1, 0],["A", 5, 0],["B", 6, 0],["B", 2, 0],["B", 5, 0],["C", 12, 0],["C", 7, 0],["C", 5, 0],["C", 5, 0]]
_ArrayDisplay(\$aArray)

Local Static \$fText = \$aArray[0][0]
Local \$iNumber = 0

For \$x = 0 To UBound(\$aArray) - 1
;~  do everything here!
If \$fText = \$aArray[\$x][0] Then
\$iNumber += 1
EndIf
If \$iNumber = \$x Then
\$aArray[_ArrayMinIndex2D(\$aArray, 0, \$x, 1)][2] = 1
\$fText = \$aArray[\$x][0]
\$iNumber = 0
EndIf
Next

_ArrayDisplay(\$aArray)

Func _ArrayMinIndex2D(ByRef \$avArray, \$iStart = 0, \$iEnd = 0, \$iCol = 0)
Local \$iMinIndex = \$iStart
For \$i = \$iStart To \$iEnd
If Number(\$avArray[\$iMinIndex][\$iCol]) > Number(\$avArray[\$i][\$iCol]) Then \$iMinIndex = \$i
Next
Return \$iMinIndex
EndFunc   ;==>_ArrayMinIndex2D```

Work only for the first group

Edited by Terenz

Nothing is so strong as gentleness. Nothing is so gentle as real strength

##### Share on other sites

Another attempt

```#include <Array.au3>

Local \$aArray[11][3] = [["A", 2, 0],["A", 3, 0],["A", 1, 0],["A", 5, 0],["B", 6, 0],["B", 2, 0],["B", 5, 0],["C", 12, 0],["C", 7, 0],["C", 5, 0],["C", 5, 0]]
;~ _ArrayDisplay(\$aArray)

Local Static \$fText = ""
Local \$iMax = 0, \$iMin = 0

For \$x = 0 To UBound(\$aArray) - 1
;~  do everything here!
If \$fText = \$aArray[\$x][0] Then
\$iMax = \$x
Else
\$fText = \$aArray[\$x][0]
If \$iMax <> \$x Then
ConsoleWrite("! MAX IDEX: " & \$iMax & @CRLF)
\$iMax = \$x
EndIf
\$iMin = \$x
ConsoleWrite("+ MIN IDEX: " & \$iMin & @CRLF)
EndIf
Next
ConsoleWrite(@CRLF)```

I'm still miss the last \$iMax and i don't know how to pass \$iMax to _ArrayMinIndex2D since the value change

Nothing is so strong as gentleness. Nothing is so gentle as real strength

##### Share on other sites

Have a look in @Melba23 signature, i know he has udf wich can do it. Same problem also solved by melba with this udf (max 2 weeks ago).

##### Share on other sites

Do you mean probably ArrayMultiColSort that is useful but for what i'd like to do require more time since i need to preserve the original sorting.

About the last \$iMax is a false problem since i can use Ubound, still searching the correct way to send \$iMin and \$iMax to _ArrayMinIndex2D.

Nothing is so strong as gentleness. Nothing is so gentle as real strength

##### Share on other sites

I'm dont know if you mean this. the question is not clear at leat for me. But I did this just for fun.

```#include <Array.au3>
Opt("MustDeclareVars", 1)

Local \$aArray[11][3] = [["A", 2, 0], ["A", 3, 0], ["A", 1, 0], ["A", 5, 0], ["B", 6, 0], ["B", 2, 0], ["B", 5, 0], ["C", 12, 0], ["C", 7, 0], ["C", 5, 0], ["C", 5, 0]]
_ArrayDisplay(\$aArray)

Local \$aArrayFind = 0
Local \$aUniqueLetters = _ArrayUnique(\$aArray)
;~ _ArrayDisplay(\$aUniqueLetters, "Unique")
Local \$aFindValues = 0
Local \$iMinIndex = 0
Local \$iMin = 0

For \$i = 1 To \$aUniqueLetters[0]
\$aArrayFind = _ArrayFindAll(\$aArray, \$aUniqueLetters[\$i])
;~  _ArrayDisplay(\$aArrayFind, "Find with " & \$aUniqueLetters[\$i])
\$aFindValues = _ArrayExtract(\$aArray, \$aArrayFind[0], \$aArrayFind[UBound(\$aArrayFind) - 1])
\$iMin = _ArrayMin(\$aFindValues, 1, -1, -1, 1)
\$iMinIndex = _ArraySearch(\$aFindValues, \$iMin, 0, 0, 0, 0, 1, 1) + \$aArrayFind[0]
ConsoleWrite(\$iMinIndex & @CRLF)
\$aArray[\$iMinIndex][2] = \$iMin
;~  _ArrayDisplay(\$aFindValues, "Extracted")
Next

_ArrayDisplay(\$aArray)```

It could be done better/faster without a lot of Array functions but I dont have time to...

Saludos

Sometimes I learn, Sometimes I teach...

AutoIt...

##### Share on other sites

Too much _Array functions but thanks anyway

What is unclear for you in my OP?

An array, on [0] are strings, [1] numbers and [2] all zeros reserved for this function. For every group of items ( three groups, four A, three B, four C) i need to get the value with the lowest number. Example the first group of A we have 2-3-1-5, 1 is the lowest value so \$aArray[3][2] = 1

My idea was take the Min and Max value for each group ( in the example is 0,3 - 4,6 - 7,10 ) and the use _ArrayMinIndex2D for extract the lowest number. I need to do all the operation in the main For...To or it will take too much time.

Edited by Terenz

Nothing is so strong as gentleness. Nothing is so gentle as real strength

##### Share on other sites

mmm so is this right?

```#include <Array.au3>
Opt("MustDeclareVars", 1)

Local \$aArray[11][3] = [["A", 2, 0], ["A", 3, 0], ["A", 1, 0], ["A", 5, 0], ["B", 6, 0], ["B", 2, 0], ["B", 5, 0], ["C", 12, 0], ["C", 7, 0], ["C", 5, 0], ["C", 5, 0]]
_ArrayDisplay(\$aArray)

Local \$aArrayFind = 0
Local \$aUniqueLetters = _ArrayUnique(\$aArray)
;~ _ArrayDisplay(\$aUniqueLetters, "Unique")
Local \$aFindValues = 0
Local \$iMinIndex = 0
Local \$iMin = 0
Local \$iManIndex = 0
Local \$iMax=0

For \$i = 1 To \$aUniqueLetters[0]
\$aArrayFind = _ArrayFindAll(\$aArray, \$aUniqueLetters[\$i])
;~  _ArrayDisplay(\$aArrayFind, "Find with " & \$aUniqueLetters[\$i])
\$aFindValues = _ArrayExtract(\$aArray, \$aArrayFind[0], \$aArrayFind[UBound(\$aArrayFind) - 1])
\$iMin = _ArrayMax(\$aFindValues, 1, -1, -1, 1)
\$iMinIndex = _ArraySearch(\$aFindValues, \$iMin, 0, 0, 0, 0, 1, 1) + \$aArrayFind[0]
\$iMax = _ArrayMin(\$aFindValues, 1, -1, -1, 1)
\$iManIndex = _ArraySearch(\$aFindValues, \$iMax, 0, 0, 0, 0, 1, 1) + \$aArrayFind[0]

ConsoleWrite(\$iMinIndex & @CRLF)
\$aArray[\$iMinIndex][2] = 1
\$aArray[\$iManIndex][2] = 1
;~  _ArrayDisplay(\$aFindValues, "Extracted")
Next

_ArrayDisplay(\$aArray)```

Saludos

Sometimes I learn, Sometimes I teach...

AutoIt...

##### Share on other sites
3 hours ago, Danyfirex said:

mmm so is this right?

No

Seems also too much complex for the goal. Launch this

```#include <Array.au3>

Local \$aArray[11][3] = [["A", 2, 0],["A", 3, 0],["A", 1, 0],["A", 5, 0],["B", 6, 0],["B", 2, 0],["B", 5, 0],["C", 12, 0],["C", 7, 0],["C", 5, 0],["C", 5, 0]]
_ArrayDisplay(\$aArray)

Local Static \$fText = \$aArray[0][0]
Local \$iNumber = 0, \$TEST = 1

For \$i = 0 To UBound(\$aArray) - 1
ConsoleWrite(\$i)
If \$TEST = 1 Then
Do
\$iNumber += 1
If \$iNumber > (UBound(\$aArray) - 1) Then ExitLoop
Until \$fText <> \$aArray[\$iNumber][0]
\$aArray[_ArrayMinIndex2D(\$aArray, \$i, (\$iNumber - 1), 1)][2] = 1
If \$iNumber > (UBound(\$aArray) - 1) Then ExitLoop ; HERE!!!!!!!!!!
\$fText = \$aArray[\$iNumber][0]
\$i = (\$iNumber - 1) ; HERE!!!!!!!!!!
EndIf
Next

_ArrayDisplay(\$aArray)

Func _ArrayMinIndex2D(ByRef \$avArray, \$iStart = 0, \$iEnd = 0, \$iCol = 0)
Local \$iMinIndex = \$iStart
For \$i = \$iStart To \$iEnd
If Number(\$avArray[\$iMinIndex][\$iCol]) > Number(\$avArray[\$i][\$iCol]) Then \$iMinIndex = \$i
Next
Return \$iMinIndex
EndFunc   ;==>_ArrayMinIndex2D```

The expected result is right ( 1 element for group - take only the lowest number for each groups - 3 group = 3 numbers ) but there are two main problem of that script:

1) I can't exitloop in that way, first comment

2) I'll change the value of \$i and i can't do it since i'm do other things in that For...To, second comment

But the result is what i'd like to have. Thanks for asking

Edited by Terenz

Nothing is so strong as gentleness. Nothing is so gentle as real strength

##### Share on other sites

Without knowing the reason why you cannot use ExitLoop, it's hard to find a suitable solution. However some general comments: Have you thought of using ContinueLoop 2? You can control what happens inside the loops by using boolean variables: If \$bThis = True Then etc...

Edited by czardas

##### Share on other sites

I don't know your final goal, anyway, here I create a new array with wanted values,
(element [3] of the new array says the position where is located this smallest number in the original array).
I also assume that all the elements of the same groups are already consecutive each other

```#include <Array.au3>
Local \$aArray[11][3] = [["A", 2, 0],["A", 3, 0],["A", 1, 0],["A", 5, 0],["B", 6, 0],["B", 2, 0],["B", 5, 0],["C", 12, 0],["C", 7, 0],["C", 5, 0],["C", 5, 0]]
_ArrayDisplay(\$aArray)
; _ArraySort(\$aArray)

\$aResult = _ArrayUnique(\$aArray, 0, 0, 0, 0) ; how many different letters ?
ReDim \$aResult[UBound(\$aResult)][3] ; redim (and clear) \$aResult
; \$aResult[n][0] letter
; \$aResult[n][1] lowest number
; \$aResult[n][2] position in original array

Local \$ndx = 0

\$aResult[\$ndx][0] = \$aArray[0][0]
\$aResult[\$ndx][1] = \$aArray[0][1]
\$aResult[\$ndx][2] = 0

For \$i = 0 To UBound(\$aArray) - 1

If \$aArray[\$i][0] <> \$aResult[\$ndx][0] Then ; letter (group) changed ?
\$ndx += 1
\$aResult[\$ndx][0] = \$aArray[\$i][0]
\$aResult[\$ndx][1] = \$aArray[\$i][1]
\$aResult[\$ndx][2] = \$i
EndIf

If \$aArray[\$i][1] < \$aResult[\$ndx][1] Then ; smaller number ?
\$aResult[\$ndx][1] = \$aArray[\$i][1]
\$aResult[\$ndx][2] = \$i
EndIf

Next
_ArrayDisplay(\$aResult)```

small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt....

##### Share on other sites

Code incomplete...deleted...

Edited by kylomas

Forum Rules         Procedure for posting code

"I like pigs.  Dogs look up to us.  Cats look down on us.  Pigs treat us as equals."

- Sir Winston Churchill

##### Share on other sites

A little variation, to my previous post#10, to allow also the update of the original array by marking the lowest numbers.
At the end  you will have 2 arrays: the original array with marks on third column, and a new array that holds only the lowest numbers for each group and indexes of their positions in the original array.
All in a single pass of course.

```#include <Array.au3>
Local \$aArray[20][3] = [["A", 2, 0],["A", 3, 0],["A", 1, 0],["A", 5, 0],["B", 6, 0],["B", 2, 0],["B", 5, 0],["C", 12, 0],["C", 7, 0],["C", 5, 0],["C", 5, 0],["X", 0, 0],["X", 3, 0],["X", -1, 0],["Y", -1, 0],["Y", -2, 0],["Y", -1, 0],["Y", 5, 0],["Z", 12.1, 0],["Z", 12, 0]]

_ArrayDisplay(\$aArray)
; _ArraySort(\$aArray)

\$aResult = _ArrayUnique(\$aArray, 0, 0, 0, 0) ; how many different letters ?
ReDim \$aResult[UBound(\$aResult)][3] ; redim (and clear) \$aResult
; \$aResult[n][0] letter (group name)
; \$aResult[n][1] lowest number
; \$aResult[n][2] position in original array

Local \$ndx = 0, \$i = 0
_Update_Arrays(\$aArray, \$aResult, \$i, \$ndx)
For \$i = 0 To UBound(\$aArray) - 1
;~  do everything here!
If \$aArray[\$i][0] <> \$aResult[\$ndx][0] Then ; letter (group) changed ?
\$ndx += 1
_Update_Arrays(\$aArray, \$aResult, \$i, \$ndx)
EndIf
If \$aArray[\$i][1] < \$aResult[\$ndx][1] Then ; found a smaller number ?
_Update_Arrays(\$aArray, \$aResult, \$i, \$ndx)
EndIf
Next
_ArrayDisplay(\$aArray)
_ArrayDisplay(\$aResult) ; holds only lowest numbers and related indexes

Func _Update_Arrays(ByRef \$aArray, ByRef \$aResult, \$i, \$ndx) ; updates arrays
\$aResult[\$ndx][0] = \$aArray[\$i][0]
\$aResult[\$ndx][1] = \$aArray[\$i][1]
\$aArray[\$aResult[\$ndx][2]][2] = 0 ; reset previous mark of min
\$aResult[\$ndx][2] = \$i ;            save index of new min
\$aArray[\$aResult[\$ndx][2]][2] = "<- lowest in " & \$aResult[\$ndx][0] ; mark new min
EndFunc   ;==>_Update_Arrays```

Edited by Chimp

small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt....

##### Share on other sites

Terenz,

Another way to look at the problem...

```#include <Array.au3>
#include <sqlite.au3>

Local \$aArray[11][3] = [["A", 2, 20], ["A", 3, 7], ["C", 10, 100], ["A", 5, 0], ["B", 6, 0], ["B", 2, 0], ["B", 5, 0], ["Z", 12, 90], ["C", 7, 0], ["C", 5, 0], ["C", 5, 0]]

_SQLite_Startup()
If @error Then Exit MsgBox(17, 'DLL Load Error', _SQLite_ErrMsg())

_SQLite_Open()
If @error Then Exit MsgBox(17, 'Memory DB Open Error', 'Error Code = ' & @extended)

_SQLite_Exec(-1, 'drop table if exists tbl1; create table tbl1 (Alpha, Our_Num, Who_Knows);')

Local \$sql

For \$i = 0 To UBound(\$aArray) - 1
\$sql &= 'insert into tbl1 values(' & _SQLite_FastEscape(\$aArray[\$i][0]) & ','
For \$j = 1 To UBound(\$aArray, 2) - 1
\$sql &= \$aArray[\$i][\$j] & ','
Next
\$sql = StringTrimRight(\$sql, 1) & ');'
Next

_SQLite_Exec(-1, \$sql)

Local \$rows, \$cols, \$arslt

\$sql = 'select Alpha as "Group", min(Our_Num) as "Lowest Number" from tbl1 group by Alpha;'
_SQLite_GetTable2d(-1, \$sql, \$arslt, \$rows, \$cols)
_ArrayDisplay(\$arslt, 'Results')

_SQLite_Close()
_SQLite_Shutdown()```

kylomas

Edited by kylomas

Forum Rules         Procedure for posting code

"I like pigs.  Dogs look up to us.  Cats look down on us.  Pigs treat us as equals."

- Sir Winston Churchill

## Create an account

Register a new account

×

• Wiki

• Back

• Git