An Array from A to Z

G

Greg Maxey

myArray = Array("A", "B", "C", "D", "E", "F", "G", _
"H", "I", "J", "K", "L", "M", "N", "O", _
"P", "Q", "R", "S", "T", "U", "V", "W", _
"X", "Y", "Z")

Is there a better way?
 
J

Jezebel

Don't know what constitutes 'better', but you could have

For i = 1 to 26
myArray(i) = chr$(64+ i)
Next

But why not just do this on the fly? Ie, wherever your code has
myArray(Index), use chr$(64 + Index) instead -- slightly more readable, and
possibly better performance.
 
G

Greg Maxey

Jezebel,

I noticed how you used the value 64 in your reply to the magnification
question in the general group.

My question here is is there a better way of creating a large array when the
result is a logical sequence. Like say I wanted an array of the first 17
elements (I think that is the right term) of the Fibonacci sequence or (0,
1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987), is there a
way to define the first few and the last and VBA fills in the blanks i.e.,

Array("A", "B", "C", ..... "Z")
Array("0", "1", "1", "2", "3", "5", ...... "987")
 
J

Jezebel

I don't think there's a general answer to that. If the series can be
determined by function (as with Fibanacci) you could write an algorithm for
the function and populate the array that way --

Sub Fibonacci(Count as long, Array() as long)

Dim pIndex as long

Redim Array(0 to Count - 1)
Array(0) = 0
Array(1) = 1
For pIndex = 2 to Count - 1
Array(pIndex) = Array(pIndex - 1) + Array(pIndex - 2)
Next

End Sub

It's a trade off, of initial processing vs code complexity vs
maintainability. In the case of Fibonnaci, if you want the first dozen or so
it's much of a muchness. If you want the first few thousand, then spelling
them out would be a lot of code and a nightmare of proofreading.

Early basic had the very useful DATA and READ instructions, intended for
exactly this purpose. It's a shame they were removed from the language.

There's a chapter on this issue in one of Knuth's classic textbooks. He uses
the example of a program that needs an array of the first n prime numbers.
You can write a prime number generator to fill the array, but -- he points
out -- it's much simpler to set up a bitmap containing 1 to p(n) bits, each
bit true if the corresponding number is prime. Not only quicker to
initialize and use, but the length of your bitmap is likely to be shorter
than would be the corresponding algorithm code.
 
G

Greg Maxey

Jezebel,

Thanks. While a simple "no" would have been clear as a bell I am not sure I
understand everything you said here. It is late and I will try to get my
head around it tomorrow. :)
 
J

JBNewsGroup

Hi Jezebel,

Just an aside. This is the first time in 25 years that I have ever seen a
reference to Knuth's series of books. I thought that the only people that
knew about them were graduates of NYU and compiler and operating system
designers. It is refreshing that someone else knows about them.

Jerry Bodoff

Jezebel said:
I don't think there's a general answer to that. If the series can be
determined by function (as with Fibanacci) you could write an algorithm for
the function and populate the array that way --

Sub Fibonacci(Count as long, Array() as long)

Dim pIndex as long

Redim Array(0 to Count - 1)
Array(0) = 0
Array(1) = 1
For pIndex = 2 to Count - 1
Array(pIndex) = Array(pIndex - 1) + Array(pIndex - 2)
Next

End Sub

It's a trade off, of initial processing vs code complexity vs
maintainability. In the case of Fibonnaci, if you want the first dozen or so
it's much of a muchness. If you want the first few thousand, then spelling
them out would be a lot of code and a nightmare of proofreading.

Early basic had the very useful DATA and READ instructions, intended for
exactly this purpose. It's a shame they were removed from the language.

There's a chapter on this issue in one of Knuth's classic textbooks. He uses
the example of a program that needs an array of the first n prime numbers.
You can write a prime number generator to fill the array, but -- he points
out -- it's much simpler to set up a bitmap containing 1 to p(n) bits, each
bit true if the corresponding number is prime. Not only quicker to
initialize and use, but the length of your bitmap is likely to be shorter
than would be the corresponding algorithm code.
 
J

JBNewsGroup

Hi Jezebel,

To generate the array how about:

For J = Asc("A") To Asc("Z")
myArray(J) = Chr$(J)
Next J

Just a suggestion as a lot of people may not know where you got the value
64. If lower case is needed then "a" and "z" can be substituted and one
would not have to know that 96 is to be added to the index.

Jerry Bodoff
Jezebel said:
Don't know what constitutes 'better', but you could have

For i = 1 to 26
myArray(i) = chr$(64+ i)
Next

But why not just do this on the fly? Ie, wherever your code has
myArray(Index), use chr$(64 + Index) instead -- slightly more readable, and
possibly better performance.
 
J

Jezebel

That's elegant. Any suggestions for the Riemann zeta function?



JBNewsGroup said:
Hi Jezebel,

To generate the array how about:

For J = Asc("A") To Asc("Z")
myArray(J) = Chr$(J)
Next J

Just a suggestion as a lot of people may not know where you got the value
64. If lower case is needed then "a" and "z" can be substituted and one
would not have to know that 96 is to be added to the index.

Jerry Bodoff
 
J

Jonathan West

Greg Maxey said:
myArray = Array("A", "B", "C", "D", "E", "F", "G", _
"H", "I", "J", "K", "L", "M", "N", "O", _
"P", "Q", "R", "S", "T", "U", "V", "W", _
"X", "Y", "Z")

Is there a better way?

It depends on what you call "better". If the way you have is "good enough"
then searching for a better way is unnecessary.

But to decide whether you need to search further, we need to define these
terms. As far as I'm concerned, the following definitions are reasonable in
this context.

"good enough"
1. the code achieves the desired result
2. it takes an acceptable amount of time to achieve the desired result and
is efficient in the use of computer resources
3. It is as self-containeed as practical and not unnecessarily dependent on
other code in the program
4. it is reasonably easy to see how the code achieves the result in case you
decide to adapt it to another purpose later.
5. As far as is reasonably foreseeable and practical, it minimizes platform
dependencies and therefore the risk of breaking if moved to a new platform

"better"
1. corrects an incorrect result
2. achieves noticeable improvements in overall execution time or other use
of resources
3. reduces the risk of unexpected interactions with other parts of the
program
4. makes the code easier to read
5. reduces platform dependencies

In the case of this particular code sample, what you have now achieves the
necessary result. I doubt that you are trying to do this repeatedly many
times in a tight loop, so improvements in execution time will be negligable,
it is a small piece of code so resource allogation (e.g. memory) is not
significant. The coede is self-contained, and it is perfectly clear how the
result is being achieved. Therefore your code is good enough.

Of course, there are other ways by which you could do the same thing. Others
have suggested different approaches. I'll add one other.

myArray = Split("A B C D E F G H I J K L M N O P Q R S T U V W X Y Z", " ")


In my opinion, Jezebel's code is less understandable and depends on the fact
that the underlying encoding of strings is ANSI. It might be faster (that
would have to be benchmarked) but it is such a small piece of code that
marginal speed changes are not going to matter in the overall execution time
of your program. But it's better not to to introduce dependencies if you
don't need to. Introducing unnecessary dependencies means that you code has
that much more chance of breaking if and when you have to make use of it on
a different platform, such as a new version of Word, a new version of
Windows, or a non-windows platform.

Jerry's code is also in my view a bit less readable. While it doesn't depend
on the exact ANSI coding, it does assume that the characters A to Z all have
consecutive code values. Of course, that assumption is true for ANSI coding
and also for Unicode, but why run the (albeit remote) risk that somebody
will change it? Also, if you find that you need to adapt your code for other
European languages with additional or accented characters, you will end up
having to change things altogether, rather than just plugging in the
additional characters in their appropriate places in the array, because the
additional characters do not have ANSI codes that are consecutive.

Remember also that even now, character codes for some characters are
different between Word for Windows and Word for Macintosh, so this isn't
quite the hypothetical issue that you might otherwise think. For instance, I
believe that a non-breaking space has a different code on the two platforms.
(I don't have a Mac handy to check this, so I'm going on memory).

From your recent questions, I get the sense that you are engaged in a wholly
laudable attempt to make your code as good as it can be, but I think at
times you are overdoing it and not trusting yourself to accept that it is
"good enough" for your purpose.
 
G

Greg Maxey

Jonanthan,

Thanks for the lessons.

How do you breakup
myArray = Split("A B C D E F G H I J K L M N O P Q R S T U V W X Y Z", " ")
over two lines. I have tried space and underscore but the complilier
doesn't seem to like it.
 
G

Greg Maxey

Jezebel/Jerry

I am trying to experiment with some of your methods. I keep gettign a Run
time error "13" Type mismatch on the lines:

myArray(J) = Chr$(J)
myArray(i) = chr$(64+ i)

Suggestions?
 
G

Greg Maxey

Here is my whole code so you can see where the error is being generated. It
could be that I am incorrectly applying your suggestions.

Sub ScratchMacroXX()
Dim magVar As String
Dim myRange As Range
Dim myArray

'Type your example M51235W2 in the document and select it
Set myRange = Selection.Range
If Left$(myRange.Text, 1) = "M" Then
For J = Asc("A") To Asc("Z")
myArray(J) = Chr$(J)
If Mid$(myRange.Text, 7, 1) = myArray(J) Then
magVar = i + 1 & "x Magnification"
End If
Next J
myRange = Left$(myRange, 6)
MsgBox magVar
End If
End Sub
 
J

Jonathan West

Hi Greg,

Although you have declared myArray as a Variant (which can contain an
array), you haven't yet actually told the program you want it to hold an
array. You need to use ReDim for this purpose, like this

Also, you haven't declared i or J as anything at all. They should both be
declared as Long.

Furthermore, i is zero by default, and you never change its value, so magVar
will always return the string "1x Magnification"


Sub ScratchMacroXX()
Dim magVar As String
Dim myRange As Range
Dim myArray As Variant
Dim i as Long
Dim J as Long

'Type your example M51235W2 in the document and select it
Set myRange = Selection.Range
If Left$(myRange.Text, 1) = "M" Then
ReDim myArray(Asc("A") To Asc("Z"))
For J = Asc("A") To Asc("Z")
myArray(J) = Chr$(J)
If Mid$(myRange.Text, 7, 1) = myArray(J) Then
magVar = i + 1 & "x Magnification"
End If
Next J
myRange = Left$(myRange, 6)
MsgBox magVar
End If
End Sub


--
Regards
Jonathan West - Word MVP
www.intelligentdocuments.co.uk
Please reply to the newsgroup
 
G

Greg Maxey

Jonathan,

Copy All. Thanks. I was working with some ideas Jezeble and Jerry posted
and was half baked between the two. Actually I am not even using the "i"
but J - 64 to return a factor 1 to 26.
 
J

JBNewsGroup

Hi Greg,

FYI. If you are using my Asc form you could use J - Asc("A") + 1 to return
an index of 1 to 26.
In this case I would define a variable: Start = Asc("A") and the loop would
be For J = Start to ASC("Z") and the index would then be J - Start + 1. As
Jonathan says the time for any process would be pretty much insignificant.

Jerry B
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top