In the following example a variant array is populated with some string values which are then looked up in different ways:
dim v1 as Variant, v2 as Variant, vAr() as variant
dim idx as integer, Index1 as integer, Index2 as integer, Index3 as integer
for idx = 0 to 2
v1 = "Value-" + str(idx)
vAr.Append v1
next idx
idx = 1
v1 = "Value-" + str(idx)
v2 = vAr(idx)
Index1 = vAr.IndexOf(v1)
Index2 = vAr.IndexOf(v2)
Index3 = -1
for idx = 0 to 2
if vAr(idx) = v1 then Index3 = idx
next idx
The expected outcome would be Index1 = Index2 = Index3 = 1
Actual outcome is Index1 = -1, Index2 = Index3 = 1
Encodings are the same in all cases, I checked that.
The same code using string variables and arrays will give the expected result though.
Is there a way to have VariantArray.IndexOf to find any values with same content but different address, or should I file a bug report?
This was tested on Windows 7 Pro with Xojo 2017R3 and Xojo2016R3.
Thanks in advance
It’s funny you mention this as I just ran into it myself. It seems to be treating Variants like objects so it will only match on address, not content.
Thanks for the reply. So I assume you consider this a bug too?
If so, the question would be what to make of it.
I did see Feedback Case #43433 by Tobias Bussmann, but that one is dated April 2016 and has not even been reviewed.
No, I’m not sure this is a bug, it may be by design and it’s easy enough to work around.
If the array is only strings, make it a string array. If it can be mixed, loop through it as you do but compare Type before content.
Well, thanks again and yes, from a pragmatic point of view you are right. So I will just assume behavior by design and write my own extension method which I need for looking up dictionary values (as opposed to keys).
Function VariantIndexOf(extends pDataArr() as variant, pFindWhat as variant) As integer
dim iMax as integer = pDataArr.UBound
for idx as integer = 0 to iMax
if pFindWhat.Type = pDataArr(idx).Type then
if pFindWhat = pDataArr(idx) then return Idx
end if
next idx
return -1
End Function
You can put both tests in the same If statement:
if pFindWhat.Type = pDataArr(idx).Type and pFindWhat = pDataArr(idx) then ...
On the other had, if the array is of Auto, this works, so maybe it is a bug.
There was an extra feedbackcase for this. Which got fixed. The case I mentioned for variants (#43433) was created in response to this. And never got reviewed. Maybe something about variants makes it difficult to fix for variants.
The difference between Auto and Variant is that Auto looses it´s ambiguity once a value has been assigned. That could make comparisons more simple in case of Auto as you need not worry about 42 being equal to 42 or not.
By the way, my quick and dirty approach works well for scalar data types but will fail for objects (which is no problem for me as my usage will always be scalar data) .
[quote=396563:@Silke Arnswald]There was an extra feedbackcase for this. Which got fixed. The case I mentioned for variants (#43433) was created in response to this. And never got reviewed. Maybe something about variants makes it difficult to fix for variants.
The difference between Auto and Variant is that Auto looses it´s ambiguity once a value has been assigned. That could make comparisons more simple in case of Auto as you need not worry about 42 being equal to 42 or not.
By the way, my quick and dirty approach works well for scalar data types but will fail for objects (which is no problem for me as my usage will always be scalar data) .[/quote]
Variants will willingly convert themselves to just about any other type. Auto doesn’t - you have to do it explicitly - which makes a world of difference.
@Jason Parsley
Still it would be much more intuitive if IndexOf for variant arrays containing string data would compare values rather than adresses.
If the comparison would compare eg. hashes then the results were consistent with Dictionary.Haskey.
At the moment you can have:
Dictionary.HasKey(SomeValue) = True but Dictionary.Keys.IndexOf(SomeValue)=-1
Unfortunately this would break any code that relied on comparing addresses, so its unlikely to change.
[quote]At the moment you can have:
Dictionary.HasKey(SomeValue) = True but Dictionary.Keys.IndexOf(SomeValue)=-1[/quote]
The order of elements in a dictionary is not guaranteed to be static, so this would be useless anyway.
@Greg O’Lone
First, thanks for your reply. I know you all have tight schedules:-)
The point I really tried to make is not whether or not this is a bug but that the behavior is very unexpected.
It is different from AUTO and it breaks the assumption that something EQUAL to an array element should be found.
If Xojo wants it to be that way then it would be nice to have a warning in the language reference and maybe close any open feedback cases on the topic by making clear it’s by design. That would have saved me quite some work and frustration.
Btw: While index values on dictionaries are not static, you can use them for a “reverse Lookup” (is this value part of the dictionary and if so, what is it’s key?). That brought me here originally.
If someone is relying on a Variant to track the address of a scalar, they deserve to have their code broken.
But it this is really a concern, it can be addressed with an optional parameter. compareByValue As Boolean = False