"Sorting" an array of CAE.FEElement()?

to all

I have a small function which extract all the CAE.FEElement from a user supplied group name . In the "main" function I later loop through the returned array of CAE.FEElement. At the end the "main" program some data is extracted from each element and written to a .csv file. The format of the data is
Elm ID, Result 1, Result 2, Result 3

and so on on for every elements

All works as intended but I have noticed that the elements are not listed by increasing ID. It may even be a bit "random".
so the question is

Is there a way of "sorting" the array of CAE.FEElement() before the For Each ... Next Loop so that when I write the (final)" data to the csv file the element are sorted by increasing ID?

Code
-------

Function GetGroupElements(ByRef theCAEGroup As CAE.CaeGroup) As CAE.FEElement()

'Function returns an array list of CAE.FEElement within a user supplied CAE.CaeGroup

Dim elementList As ArrayList = New ArrayList

For Each obj As TaggedObject In theCAEGroup.GetEntities()

If TypeOf (obj) Is CAE.FEElement Then
Dim theElement As CAE.FEElement = obj
elementList.Add(theElement)
End if
Next obj

Return elementList.ToArray(GetType(CAE.FEElement))

End Function

Dim arrFEElmInGroupTarget() As CAE.FEElement = GetGroupElements(caeGrouptarget)

For Each FEElm as CAE.FEElement In thearrFEElm
'Get the element ID
Dim theFEElmID as Double = FEElm.Label
'do something
Next FEElm

I'd suggest using a list of type (CAE.FEElement) instead of an array list. By doing so, you can use the list object's .Sort method; you'll need to write a custom function to tell the list how to sort the FEElements, but it is really easy. You can find out more about sorting lists of objects here.

Thanks. had the vague idea of sorting by Elm ID within the function GetGroupElements() just before returning the array
I do get your point/suggestion (I think) about returning a list


Function GetGroupElements(ByRef theCAEGroup As CAE.CaeGroup) As List(Of CAE.FEElement)

Thanks
Regards

Did a bit of reading and the .Sort option is starting to make sense. I have therefore copied (without any shame) the code from the link provided (and also a couple of line from the msn website). I have one problem as the code doesn't like the use of AddressOf. See code below recognised

#Region "Import Options"
Option Strict Off
Imports System
Imports System.IO
Imports System.Collections
Imports System.Collections.Generic
Imports System.Threading
Imports System.Array
Imports System.Globalization
Imports NXOpen
Imports NXOpenUI
Imports NXOpen.UF
Imports System.Windows.Forms
Imports NXOpen.BlockStyler

#End Region

Module Module1

#Region "Variables declaration"
Public Dim theSession As Session = Session.GetSession()
Public Dim theUISession As UI = UI.GetUI
Public Dim theLW As ListingWindow = theSession.ListingWindow

Public Dim strMacroName as String = "test"

Public theNXMessageBox As NXMessageBox = theUISession.NXMessageBox
Public theNXMessageBoxTitle As String = strMacroName

'Public Dim theSimPart As NXOpen.CAE.SimPart = theSession.Parts.BaseWork

Dim ufs As UFSession = UFSession.GetUFSession()

#End Region
'--------------------------------
Sub Main()

theLW.Open()

Dim i,j,k,m,n As Integer
Dim iError As Integer = 0

Dim workSimPart As CAE.SimPart = CType(theSession.Parts.BaseWork, CAE.SimPart)

'get input from user. A group containing all the elements to process
'Allocate element in group selected to arrFEElmInGroupTarget() by calling function GetGroupElements()
Dim caeGroup1 As CAE.CaeGroup = CType(ChooseOneItem("Group containing all 1D elements", workSimPart.CaeGroups.ToArray()), CAE.CaeGroup)
Dim arrFEElmInGroupTarget() As CAE.FEElement = GetGroupElements(caeGroup1)

REM 'Dim arrFEElmID(0 To Ubound(arrFEElmInGroupTarget)) As Integer
REM For Each FEElm As CAE.FEElement In arrFEElmInGroupTarget
REM 'arrFEElmID(i) = FEElm.Label
REM Dim theFEElmID as Integer = FEElm.Label
REM theLW.WriteLine("Element ID is " & theFEElmID.ToString)
REM i +=1
REM Next FEElm

End Sub

#Region "Create group display for user"
Function ChooseOneItem(ByRef prompt As String, ByRef objs() As NXObject) As NXObject

If objs.Length = 1 Then Return objs(0)

Dim opts(13) As String
Dim a As Integer = 0
Dim ii, resp, z As Integer
Dim n_choices As Integer = objs.Length
Dim choices(n_choices) As String

For ii = 0 To n_choices - 1
choices(ii) = objs(ii).Name
If choices(ii) Is Nothing Or choices(ii).Equals("") Then choices(ii) = objs(ii).ToString
Next

Do
If (n_choices - a) < 14 Then
z = n_choices - a
Else
z = 14
End If

For ii = 0 To z - 1
opts(ii) = choices(a + ii)
Next

If ((z = 14) And ((a + z) < n_choices)) Then opts(13) = "More..."

ufs.Ui.LockUgAccess(UFConstants.UF_UI_FROM_CUSTOM) ' in case running a journal
resp = ufs.Ui.DisplayMenu(prompt, 0, opts, z)
ufs.Ui.UnlockUgAccess(UFConstants.UF_UI_FROM_CUSTOM) ' in case running a journal

Select Case resp
Case 1 ' Back
If (a = 0) Then Return Nothing
a = a - 13
Case 2 ' Cancel
Return Nothing
Case 18 ' More ...
If ((a + z) < n_choices) Then a = a + 13
Case Else ' Picked one
Return objs(a + resp - 5)
End Select
Loop While True

Return Nothing ' can't really get here

End Function
#End Region

#Region "get elements in group selected"
Function GetGroupElements(ByRef caeGroup As CAE.CaeGroup) As CAE.FEElement() 'As List(Of CAE.FEElement)
Dim elementList As ArrayList = New ArrayList

For Each obj As TaggedObject In caeGroup.GetEntities()
Try
Dim element As CAE.FEElement = CType(obj, CAE.FEElement)
If Not element Is Nothing Then
elementList.Add(element)
End If
Catch
End Try
Next

'list before sorting
For Each FEElm As CAE.FEElement In elementList

Dim theFEElmID as Integer = FEElm.Label
theLW.WriteLine("At Rank " & elementList.IndexOf(FEElm).ToString & " Element ID is: " & theFEElmID.ToString)
'theLW.WriteLine("Element ID is " & theFEElmID.ToString)
Next FEElm

'sort by Element Label (smallest to highest)
elementList.Sort(AddressOf FEElmByID)

'list after sorting
For Each FEElm As CAE.FEElement In elementList
Dim theFEElmID as Integer = FEElm.Label
theLW.WriteLine("At Rank " & elementList.IndexOf(FEElm).ToString & " Element ID is: " & theFEElmID.ToString)
Next FEElm

Return elementList.ToArray(GetType(CAE.FEElement))

End Function

Private Function FEElmByID(ByVal x As CAE.FEElement, ByVal y As CAE.FEElement) As Integer

'from NXjournaling website
'custom comparison function will take two objects (or structures, or values, etc) as input
'and must return a value that indicates the ranking of these two objects.
'When comparing two values, let's call them x and y, there are three possible outcomes:

'x > y, meaning x comes after y in the sort
'x < y, meaning x comes before y in the sort
'x = y, meaning in a sorted list either could come first
'the List.Sort method will interpret the comparison function return value:

'return value > 0: x > y
'return value < 0: x < y
'return value = 0: x = y

Dim FEElmID1 AS Integer = x.Label
Dim FEElmID2 AS Integer = y.Label

'If x.Label Is Nothing AndAlso y.Label Is Nothing Then
'Return 0
'ElseIf x.Label Is Nothing Then
'Return 0
'ElseIf y.Label Is Nothing Then
'Return 0
'Else 'Compare x to y
If x.Label > Y.Label Then Return 1
If x.Label < Y.Label Then Return -1
'FEEM ID (Label) cannot be equal!
'Return x.Label.CompareTo(y.Label)
'End If

End Function
#End Region

End Module

Thanks
Regards

You are still using an arraylist; try using a list (of CAE.FEElement).

Dim elementList as New List(Of CAE.FEElement)

Thanks. Looks like it is working (well my test seems to work!). I also tweaked the function GetGroupElements() to return a list. see code below

#Region "Import Options"
Option Strict Off
Imports System
Imports System.IO
Imports System.Collections
Imports System.Collections.Generic
Imports System.Threading
Imports System.Array
Imports System.Globalization
Imports NXOpen
Imports NXOpenUI
Imports NXOpen.UF
Imports System.Windows.Forms
Imports NXOpen.BlockStyler
#End Region

Module Module1

#Region "Variables declaration"
Public Dim theSession As Session = Session.GetSession()
Public Dim theUISession As UI = UI.GetUI
Public Dim theLW As ListingWindow = theSession.ListingWindow

Dim ufs As UFSession = UFSession.GetUFSession()

#End Region
'--------------------------------
Sub Main()

theLW.Open()

Dim i,j,k,m,n As Integer

Dim workSimPart As CAE.SimPart = CType(theSession.Parts.BaseWork, CAE.SimPart)

'get input from user. A group containing all the elements to process
'Allocate element in group selected to arrFEElmInGroupTarget() by calling function GetGroupElements()
Dim caeGroup1 As CAE.CaeGroup = CType(ChooseOneItem("Group containing all 1D elements", workSimPart.CaeGroups.ToArray()), CAE.CaeGroup)
Dim arrFEElmInGroupTarget() As CAE.FEElement = GetGroupElements(caeGroup1).ToArray

For Each FEElm As CAE.FEElement In arrFEElmInGroupTarget
Dim theFEElmID as Integer = FEElm.Label
theLW.WriteLine("Element ID is " & theFEElmID.ToString)
i +=1
Next FEElm

End Sub

'------------------------------
Function GetGroupElements(ByRef caeGroup As CAE.CaeGroup) As List(Of CAE.FEElement)

GetGroupElements = New List(Of CAE.FEElement)

For Each obj As TaggedObject In caeGroup.GetEntities()
Try
Dim element As CAE.FEElement = CType(obj, CAE.FEElement)
If Not element Is Nothing Then
elementList.Add(element)
GetGroupElements.Add(element)
End If
Catch
End Try
Next

'list before sorting
For Each FEElm As CAE.FEElement In GetGroupElements 'elementList
Dim theFEElmID as Integer = FEElm.Label
theLW.WriteLine("At Rank " & GetGroupElements.IndexOf(FEElm).ToString & " Element ID is: " & theFEElmID.ToString)
Next FEElm

'sort by Element Label (smallest to highest)
GetGroupElements.Sort(AddressOf FEElmByID)

theLW.WriteLine("")

'list after sorting
For Each FEElm As CAE.FEElement In GetGroupElements 'elementList
Dim theFEElmID as Integer = FEElm.Label
theLW.WriteLine("At Rank " & GetGroupElements.IndexOf(FEElm).ToString & " Element ID is: " & theFEElmID.ToString)
Next FEElm

End Function

'------------------------------
Private Function FEElmByID(ByVal x As CAE.FEElement, ByVal y As CAE.FEElement) As Integer

'from NXjournaling website
'custom comparison function will take two objects (or structures, or values, etc) as input
'and must return a value that indicates the ranking of these two objects.
'When comparing two values, let's call them x and y, there are three possible outcomes:

'x > y, meaning x comes after y in the sort
'x < y, meaning x comes before y in the sort
'x = y, meaning in a sorted list either could come first
'the List.Sort method will interpret the comparison function return value:

'return value > 0: x > y
'return value < 0: x < y
'return value = 0: x = y

If x.Label > Y.Label Then Return 1
If x.Label < Y.Label Then Return -1

End Function

'------------------------------
Function ChooseOneItem(ByRef prompt As String, ByRef objs() As NXObject) As NXObject

If objs.Length = 1 Then Return objs(0)

Dim opts(13) As String
Dim a As Integer = 0
Dim ii, resp, z As Integer
Dim n_choices As Integer = objs.Length
Dim choices(n_choices) As String

For ii = 0 To n_choices - 1
choices(ii) = objs(ii).Name
If choices(ii) Is Nothing Or choices(ii).Equals("") Then choices(ii) = objs(ii).ToString
Next

Do
If (n_choices - a) < 14 Then
z = n_choices - a
Else
z = 14
End If

For ii = 0 To z - 1
opts(ii) = choices(a + ii)
Next

If ((z = 14) And ((a + z) < n_choices)) Then opts(13) = "More..."

ufs.Ui.LockUgAccess(UFConstants.UF_UI_FROM_CUSTOM) ' in case running a journal
resp = ufs.Ui.DisplayMenu(prompt, 0, opts, z)
ufs.Ui.UnlockUgAccess(UFConstants.UF_UI_FROM_CUSTOM) ' in case running a journal

Select Case resp
Case 1 ' Back
If (a = 0) Then Return Nothing
a = a - 13
Case 2 ' Cancel
Return Nothing
Case 18 ' More ...
If ((a + z) < n_choices) Then a = a + 13
Case Else ' Picked one
Return objs(a + resp - 5)
End Select
Loop While True

Return Nothing ' can't really get here

End Function

End Module

Thanks
Regards