Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > microsoft.public.scripting.vbscript > #11129 > unrolled thread
| Started by | noone@no.void (Reventlov) |
|---|---|
| First post | 2015-08-29 12:40 +0000 |
| Last post | 2017-03-15 21:38 -0400 |
| Articles | 18 — 5 participants |
Back to article view | Back to microsoft.public.scripting.vbscript
VbScript and .NET objects noone@no.void (Reventlov) - 2015-08-29 12:40 +0000
Re: VbScript and .NET objects "Mayayana" <mayayana@invalid.nospam> - 2015-08-29 10:39 -0400
Re: VbScript and .NET objects "Mayayana" <mayayana@invalid.nospam> - 2015-08-29 10:55 -0400
Re: VbScript and .NET objects GS <gs@v.invalid> - 2015-08-30 12:25 -0400
Re: VbScript and .NET objects "Mayayana" <mayayana@invalid.nospam> - 2015-08-30 12:55 -0400
Re: VbScript and .NET objects GS <gs@v.invalid> - 2015-08-30 13:02 -0400
Re: VbScript and .NET objects GS <gs@v.invalid> - 2015-08-30 13:10 -0400
Re: VbScript and .NET objects "Mayayana" <mayayana@invalid.nospam> - 2015-08-30 13:42 -0400
Re: VbScript and .NET objects GS <gs@v.invalid> - 2015-08-30 14:04 -0400
Re: VbScript and .NET objects "Mayayana" <mayayana@invalid.nospam> - 2015-08-30 17:05 -0400
Re: VbScript and .NET objects GS <gs@v.invalid> - 2015-08-30 17:14 -0400
Re: VbScript and .NET objects "Dave \"Crash\" Dummy" <invalid@invalid.invalid> - 2015-08-30 21:45 -0400
Re: VbScript and .NET objects "Mayayana" <mayayana@invalid.nospam> - 2015-08-30 23:09 -0400
Re: VbScript and .NET objects "Dave \"Crash\" Dummy" <invalid@invalid.invalid> - 2015-08-31 07:40 -0400
Re: VbScript and .NET objects "Mayayana" <mayayana@invalid.nospam> - 2015-08-31 09:50 -0400
Re: VbScript and .NET objects johnbeschler@gmail.com - 2017-03-15 10:24 -0700
Re: VbScript and .NET objects "Mayayana" <mayayana@invalid.nospam> - 2017-03-15 14:40 -0400
Re: VbScript and .NET objects "Mayayana" <mayayana@invalid.nospam> - 2017-03-15 21:38 -0400
| From | noone@no.void (Reventlov) |
|---|---|
| Date | 2015-08-29 12:40 +0000 |
| Subject | VbScript and .NET objects |
| Message-ID | <55e1a84f.4061562@nntp.aioe.org> |
I googled a while looking for new Active/x objects that can be instanced from VbScript.
Most of the .NET objects seem to be in DLLs that can be called with other methods but not
with CreateObject or whatever vb.net uses to connect to its objects.
I have found these examples:
Some sort of Dictionary with sorting, search, remove, insert.
A string builder with inser/replace methods
A LIFO and a FIFO stack
Any others?
Set DataList = CreateObject ("System.Collections.ArrayList")
DataList.Add "B"
DataList.Add "C"
DataList.Add "E"
DataList.Add "D"
DataList.Add "A"
DataList.Sort()
'Datalist.Reverse() 'Reverse order
'DataList.Remove("D") 'Removes an element
For Each strItem in DataList
Wscript.Echo strItem
Next
'*******************************************************************************
'Random number between 1 and 100 (1 included, 100 aparently not included)
Set objRandom = CreateObject("System.Random")
Wscript.Echo objRandom.Next_2(1,100)
'*******************************************************************************
'Concatenate strings. Faster than using "&"
set wrt = CreateObject("System.IO.StringWriter")
for i = 1 to 100000
s = CStr(i)
wrt.Write_12 s 'String. Write_11 for decimal, _10 for double, _9 for float
next
s = wrt.GetStringBuilder().ToString()
'*******************************************************************************
set sb = CreateObject("System.Text.StringBuilder")
sb.AppendFormat_5 Nothing, "{0} is a {1} number" & vbCrLf, Array(1, "loneliest")
sb.AppendFormat_5 Nothing, "{0} is a {1} number" & vbCrLf, Array(2, "happiest")
WScript.Echo sb.ToString()
'Prints:
'1 is a loneliest number
'2 is a happiest number
'*******************************************************************************
Set s = CreateObject("System.Text.StringBuilder")
s.Append_3 "I love deadlines. I like the whooshing sound they make as they fly by."
s.Append_3 "and the rest."
wscript.echo s.Length
wscript.echo s.Capacity
wscript.echo chr(s.chars(0)) 'returns first char
wscript.echo s.Replace("t", "d").Replace("l", "k").toString
s.Insert_2 7, "insert this " 'after char 7, starting from 1
WScript.Echo s.tostring()
WScript.Echo s.remove(10,4).tostring() 'Removes 4 chars starting from position 10
WScript.Echo s.tostring()
s.clear 'Removes all characters from the stringbuilder instance
'*******************************************************************************
'A sorted dictionary object
'http://www.reliance-scada.com/en/support/articles/technical/vbscript-tip-working-with-an-object-list
Dim Message, SortedList, i, s
' Initializes the message.
Message = ""
' Creates a list.
Set SortedList = CreateObject("System.Collections.SortedList")
' Fills the list.
SortedList.Add "Point", 1
SortedList.Add "Point Cloud", 2
SortedList.Add "Curve", 4
SortedList.Add "Surface", 8
SortedList.Add "Polysurface", 16
SortedList.Add "Mesh", 32
' Returns the element count.
Message = Message & "1: " & SortedList.Count & vbCrLf
' Returns the value by key.
Message = Message & "2: " & SortedList("Surface") & vbCrLf
' Returns the value at the index.
s = ""
For i = 0 To SortedList.Count - 1
s = s & CStr(SortedList.GetByIndex(i)) & " "
Next
Message = Message & "3: " & s & vbCrLf
' Verifies the existence of the key.
Message = Message & "4: " & SortedList.ContainsKey("Polysurface") & vbCrLf
' Verifies the existence of the value.
Message = Message & "5: " & SortedList.ContainsValue(16) & vbCrLf
' Returns the index of the key (searches for the element by key).
Message = Message & "6: " & SortedList.IndexOfKey("Polysurface") & vbCrLf
' Returns the index of the value (searches for the element by value).
Message = Message & "7: " & SortedList.IndexOfValue(16) & vbCrLf
' Removes the element by key.
SortedList.Remove "Polysurface" & vbCrLf
' Removes the element at the specified index.
SortedList.RemoveAt 0
' Removes all elements.
SortedList.Clear
' Releases the list.
Set SortedList = Nothing
' Displays the result.
MsgBox Message, vbSystemModal
'*******************************************************************************
'LIFO Last In First Out stack
Dim Message, Stack, Item, s
' Initializes the message.
Message = ""
' Creates a list.
Set Stack = CreateObject("System.Collections.Stack")
' Fills the list.
Stack.Push "Item_1"
Stack.Push "Item_2"
Stack.Push "Item_3"
Stack.Push "Item_4"
' Goes through the list elements.
s = ""
For Each Item In Stack
s = s & Item & " "
Next
Message = Message & "1: " & s & vbCrLf
' Converts the list into an array.
Message = Message & "2: " & Join(Stack.ToArray, ",") & vbCrLf
' Returns the element count.
Message = Message & "3: " & Stack.Count & vbCrLf
' Verifies the existence of the value.
Message = Message & "4: " & Stack.Contains("Item_2") & vbCrLf
' Removes and returns the last element.
Message = Message & "5: " & Stack.Pop & vbCrLf
' Returns the last element (without removing it).
Message = Message & "6: " & Stack.Peek & vbCrLf
' Empties the list.
Stack.Clear
' Releases the list.
Set Stack = Nothing
' Displays the result.
MsgBox Message, vbSystemModal
'*******************************************************************************
'FIFO first in first out queue
Dim Message, Queue, Item, s
' Initializes the message.
Message = ""
' Creates a list.
Set Queue = CreateObject("System.Collections.Queue")
' Fills the list.
Queue.Enqueue "Item_1"
Queue.Enqueue "Item_2"
Queue.Enqueue "Item_3"
Queue.Enqueue "Item_4"
' Goes through the list elements.
s = ""
For Each Item In Queue
s = s & Item & " "
Next
Message = Message & "1: " & s & vbCrLf
' Converts the list into an array.
Message = Message & "2: " & Join(Queue.ToArray, ",") & vbCrLf
' Returns the element count.
Message = Message & "3: " & Queue.Count & vbCrLf
' Verifies the existence of the value.
Message = Message & "4: " & Queue.Contains("Item_2") & vbCrLf
' Removes and returns the first element.
Message = Message & "5: " & Queue.Dequeue & vbCrLf
' Returns the first element (without removing it).
Message = Message & "6: " & Queue.Peek & vbCrLf
' Empties the list.
Queue.Clear
' Releases the list.
Set Queue = Nothing
' Displays the result.
MsgBox Message, vbSystemModal
--
Giovanni Cenati (Bergamo, Italy)
Write to "Reventlov" at katamail com
http://digilander.libero.it/Cenati (Esempi e programmi in VbScript)
--
[toc] | [next] | [standalone]
| From | "Mayayana" <mayayana@invalid.nospam> |
|---|---|
| Date | 2015-08-29 10:39 -0400 |
| Message-ID | <mrsftt$lp0$1@dont-email.me> |
| In reply to | #11129 |
It's never seemed to me that .Net is worth the
trouble. First, it's only useful for private code. There's
no guarantee that people with XP will have .Net
installed.
Second, I just don't see what's so great. VBS has
Dictionaries. We have arrays. The only thing I really
miss is the mid *statement*, which VB has, allowing
editing of strings without new allocations. But the
Mid statement is essentially the same as building
strings from arrays, which can be done in VBS.
Comparing .Net StringWriter or StringBuilder to
concatenation is a bit like comparing a mediocre
rake to raking your yard with a fork. You need to
compare it fairly, to the best rake you currently have.
It's *extremely* slow to do:
For i = 1 to 100000
s = s & "newstring"
Next
The reason for that is because each iteration requires
allocation of a new string, and the size of that keeps
growing. By the end each iteration is allocating almost
1 MB (or 2 MB for unicode).
But look at the following tests. Here are my results,
testing StringWriter, StringBuilder and simple VBS array
Join:
Concatenating string of instances
of the word "sample":
Time in seconds for given number of iterations:
100,000 1,000,000
Stringwriter: 1.25 9.89
StringBuilder: 1.0468 10.6406
VBS array: 0.109375 0.5625
The results vary slightly with each run, but those
numbers are typical on my machine.
It's clear from those numbers that a VBS array
far faster. And since the same relative speed holds
up for 100,000 or 1,000,000 iterations, it's clear
that instantiating and releasing the objects is not
a factor in the time required. (However, marshaling
probably is a factor. WScript needs to call into a
separate process for each iteration. As with using
any COM object, that's very inefficient.)
Here's the code, if you want to test it:
Dim s2, T1, T2
T1 = Timer
'TestSW 2
'TestA 2
TestSB 2
T2 = Timer
MsgBox Len(s2) & vbCrLf & CStr(T2 - T1)
Sub TestSW(TestVersion)
Dim SW, s1, i1, i2
Set SW = CreateObject("System.IO.StringWriter")
If TestVersion = 1 Then
i2 = 100000
Else
i2 = 1000000
End If
s1 = "sample"
For i1 = 1 to i2
SW.write_12 s1
Next
s2 = SW.GetStringBuilder().ToString()
Set SW = Nothing
End Sub
Sub TestA(TestVersion)
Dim A1(), s1, i1, i2
If TestVersion = 1 Then
i2 = 100000
Else
i2 = 1000000
End If
s1 = "sample"
ReDim A1(i2)
For i1 = 0 to i2
A1(i1) = s1
Next
s2 = Join(A1, "")
End Sub
Sub TestSB(TestVersion)
Dim SB, s1, i2, i1
s1 = "sample"
Set SB = CreateObject("System.Text.StringBuilder")
If TestVersion = 1 Then
i2 = 100000
Else
i2 = 1000000
End If
For i1 = 1 to i2
SB.Append_3 s1
Next
s2 = SB.ToString
Set SB = Nothing
End Sub
[toc] | [prev] | [next] | [standalone]
| From | "Mayayana" <mayayana@invalid.nospam> |
|---|---|
| Date | 2015-08-29 10:55 -0400 |
| Message-ID | <mrsgqv$p51$1@dont-email.me> |
| In reply to | #11130 |
Another interesting follow-up to that: I've found two things that can greatly speed up complex VBS operations. One is to always use arrays as string builders for large strings. The other, not so dramatically efficient but still worthwhile, is to do case-insensitive search. Example: You have 3 MB of text and need to search for numerous strings, which may or may not be the same case. I've found that it's notably faster to copy to string with something like s2 = LCase(s) Then s2 can be searched using binary search, while s is still the string operated on: Pt1 = Instr(1, s2, "apple", 0) s3 = Mid(s, Pt1, 5) s3 then returns apple, Apple, APPLE, etc. The non-case sensitive version of Instr has to do a more complex search. The binary version just needs to look for a matching byte value.
[toc] | [prev] | [next] | [standalone]
| From | GS <gs@v.invalid> |
|---|---|
| Date | 2015-08-30 12:25 -0400 |
| Message-ID | <mrvamc$6es$1@dont-email.me> |
| In reply to | #11132 |
> Another interesting follow-up to that: I've > found two things that can greatly speed > up complex VBS operations. One is to always > use arrays as string builders for large strings. > The other, not so dramatically efficient but > still worthwhile, is to do case-insensitive search. > > Example: > You have 3 MB of text and need to search > for numerous strings, which may or may not > be the same case. I've found that it's notably > faster to copy to string with something like > s2 = LCase(s) > Then s2 can be searched using binary search, > while s is still the string operated on: > > Pt1 = Instr(1, s2, "apple", 0) > s3 = Mid(s, Pt1, 5) > s3 then returns apple, Apple, APPLE, etc. > > The non-case sensitive version of Instr has to > do a more complex search. The binary version > just needs to look for a matching byte value. How does one implement this in VBS w/o the Mid() function?<g> -- Garry Free usenet access at http://www.eternal-september.org Classic VB Users Regroup! comp.lang.basic.visual.misc microsoft.public.vb.general.discussion
[toc] | [prev] | [next] | [standalone]
| From | "Mayayana" <mayayana@invalid.nospam> |
|---|---|
| Date | 2015-08-30 12:55 -0400 |
| Message-ID | <mrvc7v$d91$1@dont-email.me> |
| In reply to | #11133 |
| > Pt1 = Instr(1, s2, "apple", 0) | > s3 = Mid(s, Pt1, 5) | > s3 then returns apple, Apple, APPLE, etc. | > | > The non-case sensitive version of Instr has to | > do a more complex search. The binary version | > just needs to look for a matching byte value. | | How does one implement this in VBS w/o the Mid() function?<g> | I'm not sure I get that. Are you referring to my comment about missing the Mid statement in VBS? As a VBer I expect you probably know the difference between the Mid statement and the Mid function. Did I miss something? For those who don't know, the Mid statement can be used to build strings in VB: Replaces characters in s1, starting with offset 101: Mid(s1, 101) = "sample" It's very efficient because it doesn't require memory allocation. It just writes the data directly into the string variable memory. The equivalent in VBS is something like: s2 = Left(s1, 100) s3 = Right(s1, Len(s1) - 106) s1 = s2 & "sample" & s3 Three new string allocations. s2, s3 and a new allocation for s1. Very sloppy and very slow. Like binary operations, the Mid statment is a glaring omission in VBS. But using an array as a string builder comes close to the efficiency of Mid.
[toc] | [prev] | [next] | [standalone]
| From | GS <gs@v.invalid> |
|---|---|
| Date | 2015-08-30 13:02 -0400 |
| Message-ID | <mrvcsk$gj2$1@dont-email.me> |
| In reply to | #11134 |
> I'm not sure I get that. Are you referring > to my comment about missing the Mid statement > in VBS? As a VBer I expect you probably know > the difference between the Mid statement > and the Mid function. Did I miss something? No.., it's I who missed something! I didn't know there was a Mid statement and a Mid() function because I've never used the former. Clearly I need to do some homework... (I only know what I use, learning as I go thru real world projects!) -- Garry Free usenet access at http://www.eternal-september.org Classic VB Users Regroup! comp.lang.basic.visual.misc microsoft.public.vb.general.discussion
[toc] | [prev] | [next] | [standalone]
| From | GS <gs@v.invalid> |
|---|---|
| Date | 2015-08-30 13:10 -0400 |
| Message-ID | <mrvdbb$ikv$1@dont-email.me> |
| In reply to | #11135 |
>> I'm not sure I get that. Are you referring >> to my comment about missing the Mid statement >> in VBS? As a VBer I expect you probably know >> the difference between the Mid statement >> and the Mid function. Did I miss something? > > No.., it's I who missed something! I didn't know there was a Mid > statement and a Mid() function because I've never used the former. > Clearly I need to do some homework... (I only know what I use, > learning as I go thru real world projects!) Aha! interesting feature! I probably never 'stumbled' onto it due to typically using the Replace() function. Now I know.., so thanks for pointing this out! -- Garry Free usenet access at http://www.eternal-september.org Classic VB Users Regroup! comp.lang.basic.visual.misc microsoft.public.vb.general.discussion
[toc] | [prev] | [next] | [standalone]
| From | "Mayayana" <mayayana@invalid.nospam> |
|---|---|
| Date | 2015-08-30 13:42 -0400 |
| Message-ID | <mrvf0g$prn$1@dont-email.me> |
| In reply to | #11136 |
| Aha! interesting feature! I probably never 'stumbled' onto it due to | typically using the Replace() function. Now I know.., so thanks for | pointing this out! | I've actually found that Replace is also extremely slow. I'm guessing that it does a version of concatenation, so I try to avoid it in both script and VB for large strings. A few years back I was writing color syntax highlighting code for a code editor and a long, fruitful discussion happened. Mike Williams insisted that I should build an RTF string from scratch, while I was using SendMessage API versions of RTB.SelStart = x RTB.SelLength = y RTB.Selcolor = z I was sure my way must be fastest. After a lot of testing I ended up with a far faster method. It turned out Mike was right. I pointed an integer array at an LCased version of the string of text in the RTB window so that I could run a numeric tokenizing routine on that to add the RTF encoding (like "\cf0 ") for the colors into a new string using Mid. (So, for instance, the word Dim might be written to the new string as \cf3 Dim to make it show a unique color. I don't remember the exact details of RTF offhand.) I later tried other tests, like using only integer arrays with CopyMemory, but never found anything faster for ocloring text in an RTB. I'm using a VBS approach to that in the JS De-Ob I linked in the next thread, building a new string with HTML coloring code by using an array with Join. Over time I've ended up doing a lot of very intensive operations in VBS and had to try to improve them. It's surprising what speed differences can be attained with minor changes. A bit OT, but do you know this site? http://www.xbeat.net/vbspeed/ Interesting stuff for improving speeds in VB.
[toc] | [prev] | [next] | [standalone]
| From | GS <gs@v.invalid> |
|---|---|
| Date | 2015-08-30 14:04 -0400 |
| Message-ID | <mrvggj$kj$1@dont-email.me> |
| In reply to | #11137 |
> A bit OT, but do you know this site? > > http://www.xbeat.net/vbspeed/ > > Interesting stuff for improving speeds in VB. No, I don't know about this site but I'll definitely go for a cruise... Mike has also been very helpful to me in my learning process! Same goes for you and many others in the classic VB forums. Interesting about your syntax coloring! I've been using TextPad with my CncFiles Pro app as an optional editor to Notepad for about 10 years now. It supports syntax coloring and so when I started shipping it with my app I created my own gcode.syn file so it uses standard machine code editor colors for key characters/words/flags. Actually, it's pretty much the same as any editor used for writing Basic. Only personal preference change I made was to color comments light grey so the machine code stood out better! TextPad is written in Pascal (I believe), or some derivitive of it. Its syntax files are structured as text-based data files like this... <snip> ; CNC G-code Syntax File for TextPad ; Author: Garry Sansom ; Last Updated: 5/9/2007 ; Colors are default unless specified ; ~Index~ ; Keywords1: Reserved Words (all standard keywords used) ; Keywords2: M-Functions Color: Teal ; Keywords3: T-Functions Color: Olive ; Keywords4: P#### (SubProgram numbers) ; Keywords5: H#-H## (ToolOffset numbers) Color: Maroon ; Keywords6: P#-P###, PB#-PB### (Parameter/Variable numbers) Color: Maroon ; ~Special Assignments~ ; ~(Note that these are unconventional uses) ; PreprocStart: N (PositionLabel) Color: Silver ; CommentStart: F (FeedRate) Color: Teal ; CommentStartAlt: S (SpindleSpeed) Color: Fuchsia ; CommentEnd, CommentEndAlt have been assigned a single space character so only the assigned character receives color ; ; StringStart: ( (opening parenthesis for comments) Color: Silver ; StringEnd: ) (closing parenthesis for comments) </snip> ..which appears to be tab-delimited. Fortunately, TextPad includes full instruction for creating/adding our own document classes with their own syntax files.<g> -- Garry Free usenet access at http://www.eternal-september.org Classic VB Users Regroup! comp.lang.basic.visual.misc microsoft.public.vb.general.discussion
[toc] | [prev] | [next] | [standalone]
| From | "Mayayana" <mayayana@invalid.nospam> |
|---|---|
| Date | 2015-08-30 17:05 -0400 |
| Message-ID | <mrvqsn$bks$1@dont-email.me> |
| In reply to | #11138 |
| Interesting about your syntax coloring! I've been using TextPad with my | CncFiles Pro app as an optional editor to Notepad for about 10 years | now. It supports syntax coloring and so when I started shipping it with | my app I created my own gcode.syn file so it uses standard machine code | editor colors for key characters/words/flags. Actually, it's pretty | much the same as any editor used for writing Basic. Only personal | preference change I made was to color comments light grey so the | machine code stood out better! | I seem to remember an OSS control for syntax coloring being available at one point. They all seem to take the same approach, though. By coloring keywords/comments/strings they can adapt fairly easily to numerous different languages. I wrote my own code because I wanted to color variables, which are more challenging. I find it very handy in VBS, especially. As long as I declare the variable it will be colored and the case matched. That makes it easy to recognize misspellings. I also like VB6 for the way it will match case for declared variables and methods, but VB6 never provided the option to color variables. It only adjusts the case of them. It has a color for "identifiers", but that's meaningless. It includes everything that's not a string, comment or keyword. So it's really just "code color".
[toc] | [prev] | [next] | [standalone]
| From | GS <gs@v.invalid> |
|---|---|
| Date | 2015-08-30 17:14 -0400 |
| Message-ID | <mrvrkk$eja$1@dont-email.me> |
| In reply to | #11139 |
>> Interesting about your syntax coloring! I've been using TextPad with >> my CncFiles Pro app as an optional editor to Notepad for about 10 >> years now. It supports syntax coloring and so when I started >> shipping it with my app I created my own gcode.syn file so it uses >> standard machine code editor colors for key characters/words/flags. >> Actually, it's pretty much the same as any editor used for writing >> Basic. Only personal preference change I made was to color comments >> light grey so the machine code stood out better! >> > > I seem to remember an OSS control for syntax > coloring being available at one point. They all > seem to take the same approach, though. By > coloring keywords/comments/strings they can > adapt fairly easily to numerous different languages. > > I wrote my own code because I wanted to color > variables, which are more challenging. I find it very > handy in VBS, especially. As long as I declare the > variable it will be colored and the case matched. > That makes it easy to recognize misspellings. I also > like VB6 for the way it will match case for declared > variables and methods, but VB6 never provided the > option to color variables. It only adjusts the case > of them. It has a color for "identifiers", but that's > meaningless. It includes everything that's not a > string, comment or keyword. So it's really just > "code color". Sounds very useful! I now use the x64 edition of TextPad and so I suspect it's very .Net under the hood. I do know, though, there are lots of non-.Net controls out there for Delphi based apps, both x86/x64. I was looking very hard at going with Delphi to replace VB6 so I could make x64 apps, leaving VB[A]/VBS only as my main langs. I decided to stick with VB6 because I'm too heavily invested in 3rd party AX controls, and couldn't justify the cost of replacing them for Delphi use. Ok for doing x86 apps but was looking to move to x64 sooner than later. -- Garry Free usenet access at http://www.eternal-september.org Classic VB Users Regroup! comp.lang.basic.visual.misc microsoft.public.vb.general.discussion
[toc] | [prev] | [next] | [standalone]
| From | "Dave \"Crash\" Dummy" <invalid@invalid.invalid> |
|---|---|
| Date | 2015-08-30 21:45 -0400 |
| Message-ID | <ms0bfn$l4$1@dont-email.me> |
| In reply to | #11134 |
Mayayana wrote: > | > Pt1 = Instr(1, s2, "apple", 0) > | > s3 = Mid(s, Pt1, 5) > | > s3 then returns apple, Apple, APPLE, etc. > | > > | > The non-case sensitive version of Instr has to > | > do a more complex search. The binary version > | > just needs to look for a matching byte value. > | > | How does one implement this in VBS w/o the Mid() function?<g> > | > > I'm not sure I get that. Are you referring > to my comment about missing the Mid statement > in VBS? As a VBer I expect you probably know > the difference between the Mid statement > and the Mid function. Did I miss something? > > For those who don't know, the Mid statement > can be used to build strings in VB: > > Replaces characters in s1, starting with offset 101: > > Mid(s1, 101) = "sample" > > It's very efficient because it doesn't require > memory allocation. It just writes the data > directly into the string variable memory. The > equivalent in VBS is something like: > > s2 = Left(s1, 100) > s3 = Right(s1, Len(s1) - 106) > s1 = s2 & "sample" & s3 > > Three new string allocations. s2, s3 and a > new allocation for s1. Very sloppy and very > slow. Like binary operations, the Mid statment > is a glaring omission in VBS. But using an array > as a string builder comes close to the efficiency > of Mid. I use the Mid function to emulate the lacking Mid statement: s1=mid(s1,1,100) & "sample" & mid(s1,101) As always in VBS, there are several ways to perform a task. Not recommended, but works: s1=replace(s1,left(s1,100),left(s1,100) & "sample",1,1) -- Crash Registered pedophobe
[toc] | [prev] | [next] | [standalone]
| From | "Mayayana" <mayayana@invalid.nospam> |
|---|---|
| Date | 2015-08-30 23:09 -0400 |
| Message-ID | <ms0g7v$7pk$1@dont-email.me> |
| In reply to | #11141 |
| I use the Mid function to emulate the lacking Mid statement: | | s1=mid(s1,1,100) & "sample" & mid(s1,101) | That doesn't improve efficiency over the Left/Right code. It's just another way to do the same thing. You're still allocating 2 new strings, even though you're not declaring them, and then concatenating those strings in a 3rd new string. There is no substitute for the Mid statement, which is an entirely different operation, writing directly to the string bytes with no new allocations. Any of the Mid/Left/Right/Replace methods is fine for small string operations, but for extensive operations it's worthwhile to try to find a way to do it with Array/Join.
[toc] | [prev] | [next] | [standalone]
| From | "Dave \"Crash\" Dummy" <invalid@invalid.invalid> |
|---|---|
| Date | 2015-08-31 07:40 -0400 |
| Message-ID | <ms1ebk$3n3$1@dont-email.me> |
| In reply to | #11142 |
Mayayana wrote: > | I use the Mid function to emulate the lacking Mid statement: > | > | s1=mid(s1,1,100) & "sample" & mid(s1,101) > | > > That doesn't improve efficiency over the Left/Right code. > It's just another way to do the same thing. You're still > allocating 2 new strings, even though you're not declaring > them, and then concatenating those strings in a 3rd new > string. There is no substitute for the Mid statement, which > is an entirely different operation, writing directly to the > string bytes with no new allocations. > > Any of the Mid/Left/Right/Replace methods is fine for > small string operations, but for extensive operations it's > worthwhile to try to find a way to do it with Array/Join. I don't understand how you turn the initial string of x characters into an array of x elements. -- Crash A line in the sand doesn't mean much if it disappears at high tide.
[toc] | [prev] | [next] | [standalone]
| From | "Mayayana" <mayayana@invalid.nospam> |
|---|---|
| Date | 2015-08-31 09:50 -0400 |
| Message-ID | <ms1lq7$1v3$1@dont-email.me> |
| In reply to | #11143 |
| I don't understand how you turn the initial string of x characters into
| an array of x elements.
It depends on what you're doing. If you look at the
JS De-ob coloring routine I linked you can see that
it's building a new string, avoiding concatenation,
which would be unworkable on such a large scale.
I need to rebuild the string almost character by
character, and it needs to work within a reasonable
amount of time on, say, 100 KB of script.
If you want to parse a string and
add lots of substrings then the fastest method is
to parse the string non-case-sensitive and then build
the new one in an array. You can't use an array for
everything, but you can use it for many things where
one might have used the Mid statement.
For a single replacement it doesn't really matter,
but anyplace where you're doing multiple string
allocations, time can get wasted on a very large
scale.
Replace is surprisingly inefficient on large strings,
for the same reasons, so I try to use Replace only
on small strings and use array string-builders for
the big strings.
I originally got this from VB. Matthew Curland, one
of the original VB developers. He explained in his book
that Join walks the array, measuring everything, and
then only needs to allocate one big string.
In the samples below, I take a string full of "a"
and replace 6 characters at a time with "sample",
using Mid, Left/Right, or an array. The array just
assigns "sample" to each array index and then calls
Join. It's not really a real-world test, but it
demonstrates the point. My results in seconds:
string length:
100,000 300,000 1,000,000
Mid .89 51.2
LR .843 50.51 718.812
Array .015 .046 .18
While L/R was fairly quick with a string
100,000 characters long, as you can see,
it gets crazy inefficient as it gets longer.
Almost 12 minutes for a string 1,000,000
characters long! The big drain is when it
needs to allocate big strings in every iteration.
I changed the test to 300,000 from 1,000,000
after the LR test, so I wouldn't be here all morning!
That's why I have no results for a test of Mid on
a string 1,000,000 characters long.
But with the array, the length of the string
hardly matters because there is only one
large string allocation. Here's the code:
Dim s2, T1, T2
T1 = Timer
'TestMid 2
'TestLR 2
TestA1 2
T2 = Timer
MsgBox Len(s2) & vbCrLf & CStr(T2 - T1)
MsgBox s2
Sub TestMid(TestVersion)
Dim s1, i1, i2
If TestVersion = 1 Then
i2 = 100000
Else
i2 = 300000
End If
s1 = "sample"
s2 = String(i2, "a")
i1 = 10
Do While i1 < (i2 - 10)
s2 = mid(s2, 1, i1) & s1 & mid(s2, i1 + 7)
i1 = i1 + 6
Loop
End Sub
Sub TestA1(TestVersion)
Dim A1(), s1, i1, i2
If TestVersion = 1 Then
i2 = 100000
Else
i2 = 300000
End If
s1 = "sample"
ReDim A1(i2 \ 6)
For i1 = 0 to UBound(A1)
A1(i1) = s1
Next
s2 = Join(A1, "")
End Sub
Sub TestLR(TestVersion)
Dim s1, i1, i2
If TestVersion = 1 Then
i2 = 100000
Else
i2 = 300000
End If
s1 = "sample"
s2 = String(i2, "a")
i1 = 10
Do While i1 < (i2 - 10)
s2 = Left(s2, i1) & s1 & Right(s2, Len(s2) - (i1 + 6))
i1 = i1 + 6
Loop
End Sub
[toc] | [prev] | [next] | [standalone]
| From | johnbeschler@gmail.com |
|---|---|
| Date | 2017-03-15 10:24 -0700 |
| Message-ID | <aba91193-4e25-4433-9610-524fda5dee28@googlegroups.com> |
| In reply to | #11130 |
IMHO you are not doing a fair comparison.
When using Redim in VBS, you do not always know ahead of time how many iterations.
So, the correct way to do your test with VBS arrays should be like below because you need to redim the array each time you add to it.
Sub TestAR(TestVersion)
Dim A1(), s1, i1, i2
If TestVersion = 1 Then
i2 = 100000
Else
i2 = 1000000
End If
s1 = "sample"
'ReDim A1(i2)
For i1 = 0 to i2
Redim Preserve A1(i1)
A1(i1) = s1
Next
s2 = Join(A1, "")
End Sub
If you do the test that way, the array method is FAR slower:
TestSW 1: 600000 0.5625
TestA 1: 600006 0.0234375
TestAR 1: 600006 0.2226563
TestSB 1: 600000 0.4882813
TestSW 2: 6000000 5.265625
TestA 2: 6000006 0.2265625
TestAR 2: 6000006 24.03125<----------------------
TestSB 2: 6000000 4.792969
Jus sayin :)
On Saturday, August 29, 2015 at 9:36:26 AM UTC-5, Mayayana wrote:
> It's never seemed to me that .Net is worth the
> trouble. First, it's only useful for private code. There's
> no guarantee that people with XP will have .Net
> installed.
>
> Second, I just don't see what's so great. VBS has
> Dictionaries. We have arrays. The only thing I really
> miss is the mid *statement*, which VB has, allowing
> editing of strings without new allocations. But the
> Mid statement is essentially the same as building
> strings from arrays, which can be done in VBS.
> Comparing .Net StringWriter or StringBuilder to
> concatenation is a bit like comparing a mediocre
> rake to raking your yard with a fork. You need to
> compare it fairly, to the best rake you currently have.
>
> It's *extremely* slow to do:
>
> For i = 1 to 100000
> s = s & "newstring"
> Next
>
> The reason for that is because each iteration requires
> allocation of a new string, and the size of that keeps
> growing. By the end each iteration is allocating almost
> 1 MB (or 2 MB for unicode).
>
> But look at the following tests. Here are my results,
> testing StringWriter, StringBuilder and simple VBS array
> Join:
>
> Concatenating string of instances
> of the word "sample":
>
> Time in seconds for given number of iterations:
>
> 100,000 1,000,000
>
> Stringwriter: 1.25 9.89
> StringBuilder: 1.0468 10.6406
> VBS array: 0.109375 0.5625
>
> The results vary slightly with each run, but those
> numbers are typical on my machine.
> It's clear from those numbers that a VBS array
> far faster. And since the same relative speed holds
> up for 100,000 or 1,000,000 iterations, it's clear
> that instantiating and releasing the objects is not
> a factor in the time required. (However, marshaling
> probably is a factor. WScript needs to call into a
> separate process for each iteration. As with using
> any COM object, that's very inefficient.)
> Here's the code, if you want to test it:
>
> Dim s2, T1, T2
>
> T1 = Timer
> 'TestSW 2
> 'TestA 2
> TestSB 2
> T2 = Timer
>
> MsgBox Len(s2) & vbCrLf & CStr(T2 - T1)
>
> Sub TestSW(TestVersion)
> Dim SW, s1, i1, i2
> Set SW = CreateObject("System.IO.StringWriter")
> If TestVersion = 1 Then
> i2 = 100000
> Else
> i2 = 1000000
> End If
> s1 = "sample"
> For i1 = 1 to i2
> SW.write_12 s1
> Next
>
> s2 = SW.GetStringBuilder().ToString()
> Set SW = Nothing
> End Sub
>
> Sub TestA(TestVersion)
> Dim A1(), s1, i1, i2
>
> If TestVersion = 1 Then
> i2 = 100000
> Else
> i2 = 1000000
> End If
> s1 = "sample"
> ReDim A1(i2)
> For i1 = 0 to i2
> A1(i1) = s1
> Next
> s2 = Join(A1, "")
> End Sub
>
> Sub TestSB(TestVersion)
> Dim SB, s1, i2, i1
> s1 = "sample"
> Set SB = CreateObject("System.Text.StringBuilder")
> If TestVersion = 1 Then
> i2 = 100000
> Else
> i2 = 1000000
> End If
>
> For i1 = 1 to i2
> SB.Append_3 s1
> Next
>
> s2 = SB.ToString
>
> Set SB = Nothing
> End Sub
[toc] | [prev] | [next] | [standalone]
| From | "Mayayana" <mayayana@invalid.nospam> |
|---|---|
| Date | 2017-03-15 14:40 -0400 |
| Message-ID | <oac1ll$cvj$1@dont-email.me> |
| In reply to | #11587 |
<johnbeschler@gmail.com> wrote
| When using Redim in VBS, you do not always know ahead of time how many
iterations.
|
That's true. But in usage that's not very relevant.
Your version is not something any experienced scripter
would do. It's not a sensible design. It's just a demo
of the cost of Redim.
In most cases you will know the number of items,
or at least the possible upper limit. In those cases
the typical method is to start with a Redim that's
ample to hold the highest possible number. In cases
where that's not feasible, I estimate, like so:
' we know there are at least 100000 items, but
' we don't know how many total.
UB = 100000
Redim A1(UB)
i = 0
For i = 0 to unknown-number
A1(i) = x
if i = ub then
ub = ub + 100000
Redim Preserve a1(ub)
end if
next
There's then a final Redim Preserve A1(unknown-number)
That's realistic usage. I've done it many times. I
generally have an idea of the range, at least, so I
know whether to redim every 1000 or every 100000.
Testing 6 million writes seems a bit silly to me.
I've never needed to do such a thing. But that
was your test. To give .Net a headstart I even
made a poor prediction of the toital size, requiring
me to do 60 Redim Preserve. In real usage
I probably would have known the total was over
1 million. This is my result:
6 million iterations
string length of 36,000,000
String Builder 61.56 seconds
String Writer 67.34 seconds
VBS array knowing total items 3.375 seconds
VBS array having only a vague
idea of total items 6.156 seconds
So .Net is still pointless bloatware.
Also, you're posting about 5 months late. I'm guessing
you're using Google Groups. I suggest you get a real
newsreader. It works better for newsgroups and you'll
be able to take part in current discussions rather than
posting willy nilly to long-gone threads.
Here's the code for my second version:
Sub TestA(TestVersion)
Dim A1(), s1, i1, i2, UB
If TestVersion = 1 Then
i2 = 100000
Else
i2 = 6000000
End If
s1 = "sample"
UB = 100000
ReDim A1(i2)
For i1 = 0 to i2
A1(i1) = s1
If i1 = UB Then
UB = UB + 100000
ReDim Preserve A1(UB)
End If
Next
ReDim Preserve A1(i2)
s2 = Join(A1, "")
End Sub
--------------------------------------------------------------
| So, the correct way to do your test with VBS arrays should be like below
because you need to redim the array each time you add to it.
|
| Sub TestAR(TestVersion)
| Dim A1(), s1, i1, i2
|
| If TestVersion = 1 Then
| i2 = 100000
| Else
| i2 = 1000000
| End If
| s1 = "sample"
| 'ReDim A1(i2)
| For i1 = 0 to i2
| Redim Preserve A1(i1)
| A1(i1) = s1
| Next
| s2 = Join(A1, "")
| End Sub
|
| If you do the test that way, the array method is FAR slower:
|
|
| TestSW 1: 600000 0.5625
| TestA 1: 600006 0.0234375
| TestAR 1: 600006 0.2226563
| TestSB 1: 600000 0.4882813
| TestSW 2: 6000000 5.265625
| TestA 2: 6000006 0.2265625
| TestAR 2: 6000006 24.03125<----------------------
| TestSB 2: 6000000 4.792969
|
| Jus sayin :)
|
|
|
|
| On Saturday, August 29, 2015 at 9:36:26 AM UTC-5, Mayayana wrote:
| > It's never seemed to me that .Net is worth the
| > trouble. First, it's only useful for private code. There's
| > no guarantee that people with XP will have .Net
| > installed.
| >
| > Second, I just don't see what's so great. VBS has
| > Dictionaries. We have arrays. The only thing I really
| > miss is the mid *statement*, which VB has, allowing
| > editing of strings without new allocations. But the
| > Mid statement is essentially the same as building
| > strings from arrays, which can be done in VBS.
| > Comparing .Net StringWriter or StringBuilder to
| > concatenation is a bit like comparing a mediocre
| > rake to raking your yard with a fork. You need to
| > compare it fairly, to the best rake you currently have.
| >
| > It's *extremely* slow to do:
| >
| > For i = 1 to 100000
| > s = s & "newstring"
| > Next
| >
| > The reason for that is because each iteration requires
| > allocation of a new string, and the size of that keeps
| > growing. By the end each iteration is allocating almost
| > 1 MB (or 2 MB for unicode).
| >
| > But look at the following tests. Here are my results,
| > testing StringWriter, StringBuilder and simple VBS array
| > Join:
| >
| > Concatenating string of instances
| > of the word "sample":
| >
| > Time in seconds for given number of iterations:
| >
| > 100,000 1,000,000
| >
| > Stringwriter: 1.25 9.89
| > StringBuilder: 1.0468 10.6406
| > VBS array: 0.109375 0.5625
| >
| > The results vary slightly with each run, but those
| > numbers are typical on my machine.
| > It's clear from those numbers that a VBS array
| > far faster. And since the same relative speed holds
| > up for 100,000 or 1,000,000 iterations, it's clear
| > that instantiating and releasing the objects is not
| > a factor in the time required. (However, marshaling
| > probably is a factor. WScript needs to call into a
| > separate process for each iteration. As with using
| > any COM object, that's very inefficient.)
| > Here's the code, if you want to test it:
| >
| > Dim s2, T1, T2
| >
| > T1 = Timer
| > 'TestSW 2
| > 'TestA 2
| > TestSB 2
| > T2 = Timer
| >
| > MsgBox Len(s2) & vbCrLf & CStr(T2 - T1)
| >
| > Sub TestSW(TestVersion)
| > Dim SW, s1, i1, i2
| > Set SW = CreateObject("System.IO.StringWriter")
| > If TestVersion = 1 Then
| > i2 = 100000
| > Else
| > i2 = 1000000
| > End If
| > s1 = "sample"
| > For i1 = 1 to i2
| > SW.write_12 s1
| > Next
| >
| > s2 = SW.GetStringBuilder().ToString()
| > Set SW = Nothing
| > End Sub
| >
| > Sub TestA(TestVersion)
| > Dim A1(), s1, i1, i2
| >
| > If TestVersion = 1 Then
| > i2 = 100000
| > Else
| > i2 = 1000000
| > End If
| > s1 = "sample"
| > ReDim A1(i2)
| > For i1 = 0 to i2
| > A1(i1) = s1
| > Next
| > s2 = Join(A1, "")
| > End Sub
| >
| > Sub TestSB(TestVersion)
| > Dim SB, s1, i2, i1
| > s1 = "sample"
| > Set SB = CreateObject("System.Text.StringBuilder")
| > If TestVersion = 1 Then
| > i2 = 100000
| > Else
| > i2 = 1000000
| > End If
| >
| > For i1 = 1 to i2
| > SB.Append_3 s1
| > Next
| >
| > s2 = SB.ToString
| >
| > Set SB = Nothing
| > End Sub
|
[toc] | [prev] | [next] | [standalone]
| From | "Mayayana" <mayayana@invalid.nospam> |
|---|---|
| Date | 2017-03-15 21:38 -0400 |
| Message-ID | <oacq66$u4v$1@dont-email.me> |
| In reply to | #11588 |
"Mayayana" <mayayana@invalid.nospam> wrote Woops. I had a typo in my code sample. UB = 100000 ReDim A1(i2) should have been UB = 100000 Redim A1(UB) So that the array would start out at 100000. The way I had written it the array started out full size (6 million) and didn't need to be redimmed. That was the same as my original code that you questioned. Interestingly, I get almost the exact same result with 60 Redim Preserve as I did with a single Redim. The time was 6.187 seconds. I think what this demonstrates is just how wasteful it is to concatenate repeatedly. But joining an array is quick. An array is a natural string builder. With concatenation or the method you suggested, there will be 6 million allocations of memory. With Redim A1(6000000) there's only one allocation. With the gradual building, 100K at a time, there are 60 allocations, which is still a very small number. I expect the .Net methods are probably not too inefficient, once they get going. But .Net itself is a pig and none of it is known for speed. Like Java, that's not the intended strength of .Net. Rather, sandboxing and ease of coding are the intention. If .Net provided things that script can't do, like a window component or maybe graphics functions, that would be different. Unfortunately, .Net breaks COM, making it mainly incompatible with VBS. (What the heck were the Microsofties thinking with that decision?!) As far as I know, .Net offers nothing of value to script to offset the disadvantage and sheer distastefulness of loading a barrel of slop in order to run a script.
[toc] | [prev] | [standalone]
Back to top | Article view | microsoft.public.scripting.vbscript
csiph-web