Tip: Smart Sort function for arrays of objects

I recently wanted to sort an array of a custom class by one of its properties.
So I came up with a function that uses Introspection for this, so that it can be used for any array and any simple property without extra work, like this:

[code] dim dates() as Date
dates.Append new Date (1980, 4, 1)
dates.Append new Date (1912, 1, 30)
dates.Append new Date (1955, 10, 23)

dates.SortByProperty “SQLDateTime”[/code]

I’ve added the function as an example to the offocial Xojo docs, here: http://documentation.xojo.com/index.php/Introspection#Examples

Inspired by Thomas’ SortByProperty method, I adapted it to find an instance of a class in an array by one of its properties. I now use this instead of writing a Find method for each array of different classes.

Function FindByProperty(extends objs() as Object, propName as String, targetValue as Variant) As Integer
// This is a convenience function for finding an element in an array of objects by name.
  // It only works with properties of simple types such as String and Integer.
  // Adapted by Tim Brunson on 2016-8-19 from the FindByProperty method written by Sept 23, 2015 by Thomas Tempelmann. Use as you like.
  // Returns the index of the (first) matching element, and -1 if none is found.
  
  dim i as Integer
  
  if objs.Ubound < 0 then
    return -1
  end if
  
  // Get the type (class) of one of the objects in the array
  dim obj as Object = objs(0)
  dim ti as Introspection.TypeInfo = Introspection.GetType(obj)
  
  // Find the property by its name
  dim propInfo as Introspection.PropertyInfo
  for each pi as Introspection.PropertyInfo in ti.GetProperties()
    if pi.Name = propName then
      propInfo = pi
      exit
    end if
  next
  
  if propInfo = nil then
    // Unknown property
    dim exc as new KeyNotFoundException
    exc.Message = "Class '" + ti.FullName + "' has no property named '" + propName + "'"
    raise exc
  end if
 
  select case targetValue.Type
  case Variant.TypeString
    for i = 0 to objs.Ubound
      if targetValue.StringValue = propInfo.Value(objs(i)) then Return i
    next
    Return -1
  case Variant.TypeInteger
    for i = 0 to objs.Ubound
      if targetValue.IntegerValue = propInfo.Value(objs(i)) then Return i
    next
    Return -1
  case else
    // You may have to add your own cases for other searchable types if you get here
    dim exc as new TypeMismatchException
    exc.Message = "Property of '" + ti.FullName + "' is not of a simple searchable type"
    raise exc
  end select

End Function

Thanks for the code Tim. Just so you know there’s a couple unhandled edge cases.

dim obj as Object = objs(0)

objs(0) may be nil

Also the array may be used polymorphicly so the type of the first non-nil element doesn’t include all the properties of subsequent element types. This is less of a concern as all non-nil elements will at least have all properties of the arrays type. What I mean is, if you know the array contains subclass types you can’t search for those subclass properties. Hmm, I guess that’d be a dumb thing to do anyways :stuck_out_tongue: