Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

type mismatch with arrays 1

Status
Not open for further replies.

harpconn

Technical User
Jul 15, 2002
15
0
0
US
I need to de-dup an array I currently define as
DIM ISBN(500). I found nice de-dup code to use, but I'm getting a "type mismatch" error. I put together a simple test case that shows a working and non-working approach, but I don't understand why the explicit Dim won't work or how to actually use the MyArray=Array( ...) if I have to initialize a large array to establish its size or if I have to redo my code to use dynamic arrays (with which I'm less familiar.)

Somebody please clear up my ignorance. Thanks. Here's code:

THIS VERSION GETS "TYPE MISMATCH" ERROR
----------------------------------------
<%@Language=VBscript%>
<%Option Explicit%>

<html>

<head>
<title>TempTest</title>
</head>

<body>
<%
Dim MyList, MyArray(10), arrString, I

'--- Initialize full array
For I = 0 to UBound(MyArray)
MyArray(I)=&quot;&quot;
next

'--- add some test values
MyArray(0)=&quot;dog&quot;
MyArray(1)=&quot;cat&quot;
MyArray(2)=&quot;deer&quot;
MyArray(3)=&quot;dog&quot;
MyArray(4)=&quot;lion&quot;
MyArray(5)=&quot;dog&quot;

for I = 0 to UBound(MyArray)
response.write &quot;before: &quot;& MyArray(I) & &quot;<BR>&quot;
next

'--- remove duplicates
MyArray=RemDups(MyArray)

for I = 0 to UBound(MyArray)
response.write &quot;after: &quot; & MyArray(I) & &quot;<BR>&quot;
next

' remove duplicates from ISBN array
' original source code from Function RemDups(ByVal anArray)
Dim d, item, thekeys

Set d = CreateObject(&quot;Scripting.Dictionary&quot;)
d.removeall
d.CompareMode = 0
For Each item In anArray
If Not d.Exists(item) Then d.Add item, item
Next
thekeys = d.keys
Set d = Nothing
RemDups = thekeys
End Function
%>
</body>

</html>

------------------------------
THIS VERSION WORKS
------------------------------
<%@Language=VBscript%>
<%Option Explicit%>

<html>

<head>
<title>TempTest</title>
</head>

<body>
<%
Dim MyList, MyArray, arrString, I

'--- Initialize full array
MyArray=Array(&quot;&quot;,&quot;&quot;,&quot;&quot;,&quot;&quot;,&quot;&quot;,&quot;&quot;,&quot;&quot;,&quot;&quot;,&quot;&quot;,&quot;&quot;)

'--- add some test values
MyArray(0)=&quot;dog&quot;
MyArray(1)=&quot;cat&quot;
MyArray(2)=&quot;deer&quot;
MyArray(3)=&quot;dog&quot;
MyArray(4)=&quot;lion&quot;
MyArray(5)=&quot;dog&quot;

for I = 0 to UBound(MyArray)
response.write &quot;before: &quot;& MyArray(I) & &quot;<BR>&quot;
next

'--- remove duplicates
MyArray=RemDups(MyArray)

for I = 0 to UBound(MyArray)
response.write &quot;after: &quot; & MyArray(I) & &quot;<BR>&quot;
next

' remove duplicates from ISBN array
' original source code from Function RemDups(ByVal anArray)
Dim d, item, thekeys

Set d = CreateObject(&quot;Scripting.Dictionary&quot;)
d.removeall
d.CompareMode = 0
For Each item In anArray
If Not d.Exists(item) Then d.Add item, item
Next
thekeys = d.keys
Set d = Nothing
RemDups = thekeys
End Function
%>
</body>

</html>
 
The answer to your question is subtle, but simple.

You don't have a type mismatch with arrays. You have a type mismatch between an array and a variant!




It gets confusing, because while all variables in VBScript are variants, variants do indeed have types... within their &quot;variant-ness.&quot;

An array is one type of variant, but it is also possible for a general variant to contain a value that is a variant array. This sounds confusing, but what it amounts to is that you have a non-array variable with a whole array &quot;stuffed into it&quot; as its value.

You can access the elements within the embedded array with the same syntax you use to access elements in a regular array. Looking at something like MyArray(1) = &quot;cat&quot; doesn't tell you a thing about what sort of variant MyArray itself is. You can also use For Each syntax against a variant having an array value.


In your second (working) example, MyArray is not an array. It is a general variant.

The Array( ) function you use returns a variant array of variant strings. You assign this value to the (non-array) you called MyArray.

So you have this non-array MyArray, you assigned it an array value returned by Array( ), and you set some elements of this &quot;inner array&quot; to different values like &quot;cat&quot; and such.

You pass MyArray to RemDups( ), it munches on it, this thing extracts an array value by invoking the Keys( ) method on the Dictionary object d, and assigns it to the non-array variant thekeys. Then RemDups( ) assigns the array value within the non-array thekeys to the non-array return value of the function RemDups( ).

{Assign, then re-assign? Sloppy code here, you don't need thekeys.}

Then this non-array variant with a value of an array, is assigned back to your non-array variant MyArray, and things chug along in a similar manner to the end of the script.


The essential difference in your first (non-working) script example is this time you Dim'ed MyArray as an array!

Within RemDups( ), things go happily along with your array parameter. Remember, no syntax change, so VBScript doesn't give a hoot that something is different here. Just as before, the Keys( ) extraction is done, giving a non-array variant containing an array value. This is assigned to thekeys, which is reassigned to the return value of RemDups( ).

We return from RemDups( ) as before, but...

Oops! You asked VBScript to assign this &quot;non-array containing an array value&quot; to your MyArray which is an array!

Type mismatch.




Sound like gibberish? Ok, try this:


Take your first (non-working) example. Then change this:

Dim MyList, MyArray(10), arrString, I

To this:

Dim MyList, MyArray(10), MyNonArray, arrString, I

And change this:

MyArray=RemDups(MyArray)

for I = 0 to UBound(MyArray)
response.write &quot;after: &quot; & MyArray(I) & &quot;<BR>&quot;
next

To This:

MyNonArray=RemDups(MyArray)

for I = 0 to UBound(MyNonArray)
response.write &quot;after: &quot; & MyNonArray(I) & &quot;<BR>&quot;
next

Then try it again. Then go back and re-read all of that confusing stuff I wrote above.

It's all in the Microsoft VBScript documentation, you just have to read most of it to see what is going on here.

And be careful with sample code you get off free web sites. ;-)

Happy scripting!
 
Thanks. I believe I followed what you said after the third reading, and it gave me good information I didn't know before. But it seems to me that the changes you suggest leave me with a new problem, since from the point where I de-dup, I will be working with a different data type (Nonarray vs Array) which doesn't have an explicit Dim space defined and may cause reverse mismatches if I need to use it as a real array for further processing.

Maybe my laziness at wanting to pick up what looked like a &quot;solution&quot; means I should have asked a different question ... what is the best way to de-dup an array of about 300-500 elements?
 
I feel your pain.

- 1 ----------------------------------

Given:
Code:
Dim A(10), B

B = Array(&quot;&quot;, &quot;&quot;, &quot;&quot;, &quot;&quot;, &quot;&quot;, &quot;&quot;, &quot;&quot;, &quot;&quot;, &quot;&quot;, &quot;&quot;, &quot;&quot;)
Shorthand for those things is usually:

A is an array of variants
B is a variant array

What's sort of sad is, the array value within B is an array of variants too, so to be honest it ought to be:

B is a variant array of variants

But most people just say &quot;variant array&quot; and have it done with.

- 2 ----------------------------------

There isn't a good answer that I can find for you to the array stuff. The problem is that lots of VBScript built-in functions [like the Array( ) and Split( ) and Filter( ) functions] and many objects' method calls [like the Dictionary object's Keys( ) method] return a variant array value that can't be assigned back to an array of variants that was pre-dimensioned like A( ) above.

And a VBScript Function can only return a single variant, so that has to be a variant array too. Even making the Function into a Sub and trying to pass the result back as a ByRef (which will work) doesn't always solve your problem. See -- 4 -- below.

Some people just skip using stuff like A( ) then altogether - not always practical.

Others mix them up at will and just &quot;trust the force, Luke!&quot; Then when things blow up they scratch their heads for several hours and hack around it somehow - blaming Microsoft for a &quot;bug.&quot;

This ain't a bug, it's a feature. But a frustrating one I admit.

- 3 ----------------------------------

Whatever you do, avoid mixing in any JScript/Javascript! Their idea of an array is really a string with commas between values. Let's not even GO there, Ok? Thank you NetScrape. Bleh!

See this writeup when you want a real headache:


- 4 ----------------------------------

But your troubles stem from using the Dictionary object to try to remove duplicates. Even if you changed
Code:
Function RemDups(ByVal anArray)
to
Code:
Sub RemDups(ByRef anArray())
and assigned the Keys( ) result back to anArray you'd be in trouble:
Code:
'--- remove duplicates
RemDups MyArray

For I = 0 to UBound(MyArray)
  Response.Write &quot;after: &quot; & MyArray(I) & &quot;<BR>&quot;
Next

Sub RemDups(ByRef anArray())
  Dim d, item

  Set d = CreateObject(&quot;Scripting.Dictionary&quot;)
  d.RemoveAll
  d.CompareMode = 0
  For Each item In anArray
    If Not d.Exists(item) Then d.Add item, item
  Next
  anArray = d.keys
<-- type mismatch
Code:
  Set d = Nothing
End Sub
- 5 ----------------------------------

So what's a mother (VBScripter) to do?

Two choices:
[ul][li]Use a solution like your 1st one that worked, and just wiggle around any new troubles that pop up due to variant arrays.
[li]Use another &quot;de-dup&quot; process that (a.) does not use Dictionary's Keys( ) method or any other similar method or function, and (b.) does not return values via a function value like RemDups( ) does.[/ul]If I find another &quot;de-dup&quot; like that I'll pass it along, but it seems like no matter what it will have to use a loop to put stuff back into your &quot;array of variants&quot; one at a time.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top