PDA

View Full Version : Solved: Check Value of Array



RECrerar
10-08-2007, 08:41 AM
I have an array with 3 values. These Values should be 1, 2 and 3 in any order (that is 3,2,1 or 3,1,2 etc could all possible). is there a way to check if all three values are in the array other than using multiple if statments?

I'm currently using



If WG(0) = 1 then
If WG(1) = 2 And WG(2) = 3 Or WG(1) = 3 And WG(2) = 2 then
' Ok Do Stuff
Else
Msgbox("Error")
'Not Ok, do other stuff
End if
Elseif WG(1) = 2 then ' ..... etc


but this seems very long winded just to check if all three numbers of the array are the numbers I need.

Thanks in advance for any help, and if it's not that well explained please do ask for more information

RECrerar
10-08-2007, 10:13 AM
hey

Don't worry about this, Haven't found another way to do it, but realised that my conditions will be different for each different arrangement of 1,2 and 3 and therefore would need to determine which number was where later in the program anyway if I didn't do it where the above code fits in.

Sorry if anyone's been working on this

lucas
10-08-2007, 10:19 AM
Mark it solved please so others don't think it still needs attention.
Use thread tools at top of the page.

Paul_Hossler
10-08-2007, 10:21 AM
would this work for you?


Sub aaa()
Dim A(1 To 3) As Long

A(1) = 2
A(2) = 3
A(3) = 1

With Application.WorksheetFunction

MsgBox (.Average(A) = 2) And (.Max(A) = 3) And (.Min(A) = 1)

End With

End Sub


Paul

RECrerar
10-08-2007, 10:33 AM
You know that probably would work. As I said have realised I don't need to do this here, but it is the type of thing I may possibly need at somepoint, so I shall remember that. Thanks.

Robyn

Oorang
10-08-2007, 10:56 AM
Hello RECrerar,
Without knowing more about the underlying problem the logic is attempting to solve it's difficult to reduce control statements. There are a few techniques for looping through arrays or using collections or UDTs instead but I think what you are really looking to do is make your code as efficient as possible.

Without specifics it's hard to offer help, but here are a few generalizations that may be of some service. The main principle to remember that what you want is not less overall code, but code that creates the shortest possible flow-path in all conditions. Fewer operations, not fewer lines. The first step to streamlining code is to design.

Don't worry about where the information is stored or how, just consider what you need to determine if an action should be taken or not. For design purposes these conditions can usually be thought of as simple boolean values (isRed, isBlue, isCow, isKite etc.) The next step is to build an truth table (you can just excel for this). Make a column of every possible combination of variables and the desired output. Take the example below:
http://img130.imageshack.us/img130/9139/truthtableexamplegu9.png

Now you want to examine your table for commonalities. You have 8 possible combinations leading to five possible actions. In the worst case each scenario would take 3 checks to determine what action to execute. We are looking to reduce that.
The first thing to check is grouping. The Term/dispose action occurs three times, not other action reoccurs. So our only oppurtunity is this group. If you look at that Term/Dispose group you might notice is that all three share a commonality, isRabid will be true. That's a start, wowever in the isRabid group we have an invader, an error condition. To eliminate the error condition you will need a minimum of one more check, possibly two. You more check will elimate the Error condition from the group. And what is left are two entries for which you only need two checks instead of three.
An exhautive comparision of possible check orders will show that despite many seeming overlaps, this is the only scenario where all conditions did not need to be checked.
You can then implement your design with confidence knowing that while your code may have many lines, it actually has the fewest operations. I have posted some example code below for your consideration, I want you to note how I did not use If isRabid or isEndangered Then syntax. This is because vba does not short circut it's conditionals. That is to say that even if isRabid was true, it would still examine isEndangered anyway. This can really kill you if you are using function calls in your if condition. With only some exceptions, you should evaluate only one condition per IF.

I know that was long winded but I hope it helped:


Example Code:
Option Explicit

Sub Example()
Dim isEndangered As Boolean
Dim isWild As Boolean
Dim isRabid As Boolean
On Error GoTo Err_Hnd
isEndangered = True
isRabid = True
If isRabid Then
If isEndangered Then
If Not isWild Then
VBA.Err.Raise vbObjectError, "Example", "Illegal Condition"
End If
End If
TerminateDispose
Else
If isEndangered Then
If isWild Then
CatchTagRelease
Else
VBA.Err.Raise vbObjectError, "Example", "Illegal Condition"
End If
Else
If isWild Then
CatchRelease
End If
End If
End If
Exit_Proc:
On Error Resume Next
Exit Sub
Err_Hnd:
VBA.MsgBox "Error " & VBA.Err.Number & " (" & VBA.Err.Description & ") in procedure Example of Module Module1"
Resume Exit_Proc
End Sub
Sub TerminateDispose()
'Placeholder
End Sub
Sub CatchTagRelease()
'Placeholder
End Sub
Sub CatchRelease()
'Placeholder
End Sub

unmarkedhelicopter
10-08-2007, 12:02 PM
You have 8 possible combinations
Er ! 3 number slot's and any number could go in any slot (and there was not statement that they actually HAD to be just 1, 2 & 3) so there is more than 8 possible permutations.

Paul_Hossler's solution was succinct and fits the bill in my book.

If the test was for more values in more possitions, I'd probably use strings.
'Concatenate all Values e.g.
for lX = 1 to 10
sVal = lVal(lX) & "*" ' helps when breaking if values more than 9 (say)
next lX
'check overall length is as expected (assumes each val 2 characters i.e. 10 - 99)
lL = 30
if len(sVal) <> lL then msgbox "it's broke !": end
'have an array of antipated values (say sTst() )
for lX = 1 to 10
lL = lL - 3
sVal = replace(sVal, sTst(lX) & "*", "")
if len(sVal) <> lL then msgbox "it's broke !": end
next lX
msgbox "Values OK"

Edit: Made a Mistake :bug:

Oorang
10-08-2007, 01:42 PM
Er ! 3 number slot's and any number could go in any slot (and there was not statement that they actually HAD to be just 1, 2 & 3) so there is more than 8 possible permutations. True:)
Possibilities = Base^Positions
However, my hypothetical was using three boolean values (three positions). In boolean you have two possibilities, true and false. Therefore base = 2 and 2^3 = 8 :yes

Paul_Hossler's solution was succinct and fits the bill in my book.If you're happy, I'm happy :)

RECrerar
10-09-2007, 12:56 AM
Wow,

Loads on information. Have training for teh next two days, so will look at in later in the week, just wanted to write a quick note to acknowledge you input, thanks, i shall get back to you.

unmarkedhelicopter
10-09-2007, 01:30 AM
True:)
Possibilities = Base^Positions
However, my hypohetical was using three boolean values (three positions). In boolean you have two possibilities, true and false. Therefore base = 2 and 2^3 = 8 :yes
If you're happy, I'm happy :)

Oorang, you are correct. I love your signiture and given "hypohetical" above when are we gonna get a 'spell check' on these forums ? ... :beerchug:

Oorang
10-09-2007, 06:31 AM
rofl we do have a spell checker in this forum... But apparently I can't be bothered to click it :)

RECrerar
10-09-2007, 09:19 AM
Hi,

I think I have this section of the code working in a satisfactory manner at the moment (probably could be improved but is okay for now). However since you spent so much time writing a very helpful explanation for me and asked about the particular workings of the project, I shall do my best to explain it.

My raw data is sets of coordinates and part references that describe a waveguide (basically a long metal tube with brackets and flanges on it) and the position of said bracket and flanges.

Most of the data is in local coordinates with a start location always equal to 0,0,0 and the direction to the first corner always being +y. I need to convert all the coordinates to the global coordinates that could be anywhere with an initial curve direction in any direction. To do this I compare the start and end local coordinates with the start and end global coordinates. The difficulties are that the local x coordinates are not necessarily the global x coordinates and the item could also be relected in any axis.

To explain this better see the example below:

LS = Local Start
LE = Local End
GS = Global Start
GE = Global End

LS = (0,0,0) LE = (15.2, 543, -827.5) GS = (2734.8, -1123, 3824.5) GE = (3562.3, -580, 3299.7).

By comparing LE - LS with GE - GS it is possible to determine which global axis the local coordinates for an axis below to and whether or not they need to be reflected:

LE-LS = (15.2, 543, -827.5) GE - GS = (827.5, -543, 15.2)

Therefore L(x) = G(z) not relected
L(y) = G(y) reflected
L(z) = G(x) reflected

The array containing the values 1,2 and 3 references G(x), G(y) and G(z) respectively and also are used as variables to determine which columns the local coordinates should be copied to. This would be fairly straight forward if I could garantee that the global coordinates given would always be correct, but them may not. If a value in the LE-LS array does not equal any of the values in the GE-GS array then it is assigned a value of 0. There is also the small possibility that there may be two value in the LE-LS array that match the same value in the GE-GS array, which again would clearly be wrong. This is why I needed to be able to check that the array contained the values 1,2 and 3 only.

The reason I realised that I needed to know the specific arangement of the numbers was to be able to know whic axes were relected and which were not.

This has turned into a bit of an essay, so I shall leave it there, hope that explains better the situation. As I said I have a working solution at the moment, probably not the neatest, but it will do for now, so this post is really just for your interest.

Regards

Robyn

unmarkedhelicopter
10-09-2007, 03:10 PM
rofl we do have a spell checker in this forum... But apparently I can't be bothered to click it :)

Sorry I still can't find it, sometimes the only thing that stops me looking a complete "ioidt" is a spell checker !

Oorang
10-09-2007, 03:28 PM
In the gray border around the "Quick-Reply" there is a check mark with "ABC" on it. That is the forum's spell checker:)

mikerickson
10-09-2007, 04:52 PM
Select Case (100 * myArray(1)) + (10 * myArray(2)) + myArray(3)
Case 123
Rem some code
Case 132
Rem some code
Case 213
Rem some code
Case 231
Rem some code
Case 312
Rem some code
Case 321
Rem some code
Case Else
MsgBox "Bad array"
End Select

unmarkedhelicopter
10-10-2007, 04:07 AM
Slightly more comprehensive bit of code :thumb
dim sTst(10) as string
'Concatenate all Values e.g.
for lX = 1 to 10
sVal = lVal(lX) & "*" ' helps when breaking if values more than 9 (say)
next lX
'check overall length is as expected (assumes each val 2 characters i.e. 10 - 99)
lL = 30
if len(sVal) <> lL then msgbox "it's broke !": end
'have an array of antipated values (say sTst() )
sTst = Array("11*", "22*", "33*", "44*", "55*", "66*", "77*", "88*", "99*", "19*")
for lX = 1 to 10
lL = lL - 3
sVal = replace(sVal, sTst(lX), "")
if len(sVal) <> lL then msgbox "it's broke !": end
next lX
msgbox "Values OK"

Oorang
10-10-2007, 06:32 AM
Hi Mike,
That's a nice trick. I suspect for small integers it would benchmark the best for everything here. You'd want to be carefull about overflow conditions though.

RECrerar
10-11-2007, 03:59 AM
Hi Mike,

I love you solution, that's so neat and smart, I think shall use it.

Unmarkedhelicopter, your solution looks very interesting, but I have to admit, I don't understand it, sorry. I would like to specifiy the parts that need explaining but other than the message boxes, I would probably have to go with all of it! If you could explain what exah line does that would be great.

unmarkedhelicopter
10-11-2007, 07:52 AM
Dim sTst(10) As String
'Concatenate all Values e.g.
For lX = 1 To 10
sVal = lVal(lX) & "*" ' helps when breaking if values more than 9 (say)
'This takes each value in your array, puts an asterix after it (so we can delineate values) and adds it to a string value (originally empty)
Next lX
'check overall length is as expected (assumes each val 2 characters i.e. 10 - 99 in this instance)
'If we have 10 values of 2 characters each (+ asterix) we have 30 chars.
lL = 30
If len(sVal) <> lL Then msgbox "it's broke !": End ' i.e. not 30 chars.
'have an array of antipated values (say sTst() )
sTst = Array("11*", "22*", "33*", "44*", "55*", "66*", "77*", "88*", "99*", "19*")
'These are the values "WE REQUIRE" to be present in the string (note the added asterix's)
For lX = 1 To 10
lL = lL - len(sTst(lX)) ' we subtract the length of what we expect to be there from the total
sVal = replace(sVal, sTst(lX), "") ' we remove the actual expected value (can be in ANY position)
If len(sVal) <> lL Then msgbox "it's broke !": End
' if the new length does NOT match the expected new length we have a problem
Next lX
msgbox "Values OK"
'code finished so must be okay

RECrerar
10-11-2007, 09:40 AM
Oh I see, thanks for the explanation.

Will stick with Mike's for this particular problem but that's very good. one thing I like about this programming thing is having to think around problems and work out clever ways to slove them.

mikerickson
10-12-2007, 12:36 PM
Glad to have helped.