Arrays

Forgive me if this is already possible in Xojo (I’m new to the language). I have an array that I’d like to search. See my code and comments below:

Dim arr() As String = Array(“Bill”, “Jane”, “Harry”, “Christopher”, “William”)

// My example adds only those names in the array that contain the letter “a” to a ListBox.
// This code works fine in Xojo.
ListBox1.RemoveAllRows
For Each item As String In arr
if item.Contains(“a”, ComparisonOptions.CaseInsensitive) then ListBox1.AddRow(item)
next

// New Feature Request:
// Update the Array keyword as follows (it would be overloaded):
// Array.FindAll(targetArray() As variant, searchFor As Variant)
// Array.FindAll(targetArray() As variant, searchFor As Variant, options As ComparisonOptions)
// Adding this functionality to the Array keyword eliminates the explicit check I had to write in the above example.
ListBox1.RemoveAllRows
For Each x as String In Array.FindAll(arr, “a”, ComparisonOptions.CaseInsensitive)
ListBox1.AddRow(x)
next

You could write your own Extends function and put this in a module with scope “Global”:

https://documentation.xojo.com/api/language/extends.html

Public Function FindAll(Extends arr() As String, find As String, Optional comparisonOption As ComparisonOptions = ComparisonOptions.CaseInsensitive) As String()
  
  Var result() As String
  
  For Each item As String In arr
    If item.Contains(find, comparisonOption) Then result.Add item
  Next
  
  Return result
End Function

Then you can call this function like in your code:

Var arr() As String = Array("Bill", "Jane", "Harry", "Christopher", "William")

For Each x as String In arr.FindAll("a")
  
  ListBox1.AddRow(x)
  
Next
3 Likes

This is a situation where Xojo could add some significantly useful functionality that we can’t easily add natively. Consider this syntax that uses a Delegate to filter the array:

Function FindLetterA(value as Variant) as Boolean
     Return v.StringValue.Contains(a, ComparisonOptions.CaseInsensitive)
End Function

Dim OriginalArray() as String

OriginalArray=Array("Bob", "Sally", "Goober", "Matilda")

Dim ItemsWithLetterA() as String

ItemsWithLetterA=OriginalArray.FilterWithDelegate(AddressOf FindLetterA)

There’s no way for a Xojo developer to create the kind of functionality without creating a version of FilterWithDelegate for each type of array (string, integer, each object class, etc). Xojo could do this in the framework in a generic way that can be applied to arrays of any type.

For an example, look at the version of Array.Sort that accepts a Delegate to do the comparison needed during sorting. This same model could be very useful for this situation.

1 Like

The problem is with Variant. You can pass any kind of variable to a function that is defined (v as variant) and all is well. A single property can interact with a variant, no problem.

However if you define a function as (v() as variant), the only thing you can pass it is an array of type variant. You cannot pass it a string array or an integer array. It just doesn’t work that way. Arrays are treated differently than simple variables.

3 Likes

Well you could achieve this with a parameter “arr As Variant”.
But then you would have to use Introspection to check what “arr” is and this is slow.

Public Sub ArrMethod(arr As Variant)
  
  Var typeInfo As Introspection.TypeInfo = Introspection.GetType(arr)
  Var fullName As String = typeInfo.FullName
  
  Select Case fullName
    
  Case "String()"
    
    Var stringArr() As String = arr
    
  Case "Integer()", "Int64()"
    
    Var integerArr() As String = arr
    
  End Select
End Sub
Var s() As String
Var i() As Integer

ArrMethod s
ArrMethod i

I cautiously suggest that - if the array is likely to be large ? - you might be better off using an in-memory database and performing a LIKE query on it to get a resultset.
Database operations on large numbers of rows is usually much faster, if that is an issue.

What you lose by that is the ability to treat the array like an array - reading and writing values by the index

eg
arr(6) = “new value”

But for reading from it, you can have an index in each record, and order a resultset by that.

Thanks StefanA. I know that I could write the routine, however my recommendation would be for the Array statement to handle it for us. It reduces the amount of code we have to maintain.

you can add feature requests via issues, the link at top in pc browser.
it could be written as:
=arr.Find("a", ComparisonOptions.CaseInsensitive)

1 Like

If some feature is not very useful for a broad range of people, and it can be written by the user, it should not be added to the framework. The KISS principle.

1 Like

a filter is very useful. but maybe the array is the wrong base for data if we have rowset.

i also like LINQ in C#

His methods proposals aren’t a generic filter.

The time to Xojo being able to handle Generics is getting narrower each year.

1 Like

I’ve used Xojo for about 20 years. I cannot recall anyone mentioning the need for such a feature, and havent needed it from Arrays myself.
Not saying it’s useless,
but the solution in the original post is 3 lines of code. What would be saved or improved by spending time on developing that change?

I’m not sure how you’re measuring/quantifying that “broad range” of people.

The KISS principle can be viewed two different ways here:

  1. Your suggestion keeps the “framework” simple.
  2. My suggestion keeps the Xojo software developer’s code simple.

A software framework is a structure that acts as a foundation so that software developers don’t have to deal with creating unnecessary extra logic from scratch.

The framework should provide a FindAll extension method to the array type.

Dim arr() As String = Array(“Bill”, “Jane”, “Harry”, “Christopher”, “William”)
For Each x as String In arr.FindAll(“L”, ComparisonOptions.CaseInsensitive)
ListBox1.AddRow(x)
next

Glad to hear that generics are getting closer and closer.

I’ve found multiple posts where users are asking how to search arrays. Some dating back to 2015.

A few posts over 10 years isn’t “This is impossible to do without the help of the framework and needs to be added.” It’s our regular Circle of Topics™, where you’ll happily get help from a few people able to rework the same answers we gave those people to help you.

In my opinion there are far better things for the staff to be focusing on (like those random crashes in Web).

I never said it was impossible to do without help of the framework. I found a way to make it work and I showed that in the original post.

I submitted a feature request for it. It’s up to the Xojo team to determine whether or not it’s something that should be added or not.

1 Like

Besides. Why WOULD the Xojo team prioritize a new feature request over system crashes?

somehow this .Find was only as remark in your example and possibly overlooked.

Like 3 or more current popular languages supporting some variant of the “supposed useful feature” seems one way of determining the popularity of such feature.

Your request is very self-centered, you need something and think many people will need too enough to cement it into the framework.

Your request can be fulfilled right now by yourself with an extension for your not very usual use case. So inflating the framework putting something used one time in each 10000 uses of an array, that can be fulfilled easily by one extension, seems not a good decision.

Your request is very specific, with a small change it would target a broader number of scenarios, like some kind of generic filter/map/reduce feature. Something like that would call my attention, and exists in some form in many current languages, and would satisfy your need and many others. But without Generics it would construct things that would be removed in the future to favor another solution using Generics, probably.

That’s why my vote is no.

And I would like Generics first, and then some kind of filter/map/reduce features later able to satisfy a huge set of options, including your “Return items in a array containing x letter”. It would return items not containing x, or equal y, and empty, or with length()>12… Also not just strings, another reduce() could handle doubles > pi or < 0, etc.

That said, I think other parts of the language need to mature a bit more first.

2 Likes