【问题标题】:VB.NET sort IEnumerable classVB.NET 排序 IEnumerable 类
【发布时间】:2013-11-01 15:10:08
【问题描述】:

我想对实现 IEnumerable 的 VB 类进行排序。 我不想要一个新对象/ linq。 它必须保持为原始对象但已排序。 这是一个示例类。

Public Class Person
    Public Sub New(ByVal fName As String, ByVal lName As String)
        Me.firstName = fName
        Me.lastName = lName
    End Sub

    Public firstName As String
    Public lastName As String
End Class

Public Class People
    Implements IEnumerable(Of Person)

    Private _people() As Person

    Public Sub New(ByVal pArray() As Person)
        _people = New Person(pArray.Length - 1) {}

        Dim i As Integer
        For i = 0 To pArray.Length - 1
            _people(i) = pArray(i)
        Next i
    End Sub

    Public Function GetEnumerator() As IEnumerator(Of Person) _
            Implements IEnumerable(Of Person).GetEnumerator
        Return DirectCast(_people, IEnumerable(Of Person)).GetEnumerator
    End Function

    Private Function System_Collections_GetEnumerator() As IEnumerator _
            Implements IEnumerable.GetEnumerator
        Return Me.GetEnumerator
    End Function
End Class

我知道我可以使用 LINQ,但是我得到了一个新对象,而不是原来的排序对象。 使用全局“peopleList”对象的地方太多了,所以我需要对“peopleList”进行排序,而不是对“People”的新排序列表。

Dim peopleList As New People({ _
    New Person("John", "Smith"), _
    New Person("Jim", "Johnson"), _
    New Person("Sue", "Rabon")})
Dim newPeopleList = From person In peopleList Order By person.firstName Select person
'OR
Dim newPeopleList = DirectCast(peopleList, IEnumerable(Of Person)).ToList()
newPeopleList.Sort(Function(p1, p2) p1.firstName.CompareTo(p2.firstName))

我需要类似以下的东西。

Dim peopleList As New People({ _
    New Person("John", "Smith"), _
    New Person("Jim", "Johnson"), _
    New Person("Sue", "Rabon")})
peopleList = peopleList.Sort(Function(p) p.firstName)

我知道 IEnumerable 没有 Sort 方法。我只是把它作为一个例子来展示。 我确实可以选择修改“People”类,但最后它仍然必须实现 IEnumerable,因为我不想破坏当前的调用者。 此外,当前调用者必须能够看到已排序的“peopleList”。

【问题讨论】:

    标签: .net vb.net linq sorting ienumerable


    【解决方案1】:

    您可以在创建People 列表时对Person 对象进行排序:

    Public Sub New(ByVal pArray() As Person)
        _people = New Person(pArray.Length - 1) {}
    
        Dim i As Integer = 0
        For
        For Each person In pArray.OrderBy(Function(p) p.firstName)
            _people(i) = person
            i = i + 1
        Next i
    End Sub
    

    或者,您可以提供自己的方法来在创建内部数组后对其进行排序。像这样的东西应该可以工作:

    Public Class People
        Public Sub Sort(Of T As IComparable)(KeySelector As Func(Of Person, T))
            Array.Sort(_people, Function(x, y) KeySelector(x).CompareTo(KeySelector(y)))
        End Sub
    End Class
    

    你可以这样称呼:

    peopleList.Sort(Function(p) p.firstName)
    

    【讨论】:

    • 这是一个选项,但在我查询对象之前,其他一些方法填充了对象。因此,拥有某种“排序”方法/功能会更好。像 danielsaidi.wordpress.com/2009/08/27/… 这样的东西,但在 VB 中。
    • 我确实喜欢更新后的答案,但它不能在我的机器上使用 .NET 3.5 编译... Func(Person, T) 行——“数组边界不能出现在类型说明符中”跨度>
    • @goroth 哎呀,我的错;我的 VB.NET 有点生锈了。请参阅我的更新答案。
    • 正是我需要的。很遗憾,没有人有 VB.NET 扩展方法来执行您列出的操作。我有几个实现 IEnumerable 的类,如果我不必编辑它们中的每一个就好了,但我没有在帖子中说我需要扩展方法,所以你确实给了我我所要求的。
    • @goroth 好吧,你可以只使用 Linq 的 .OrderBy 扩展方法(我在第一个示例中使用过),但这总是会返回一个新的 IEnumerable,并且不能用于修改一个现有的对象。
    【解决方案2】:

    您可以对底层数组进行排序并使用自定义 IComparer 来适应:

    http://msdn.microsoft.com/en-us/library/bzw8611x.aspx

    类似:

    public class PersonComparer: IComparer<Person>
    {
        public int Compare(Person x, Person y)
        {            
            return x.FirstName.CompareTo(y.FirstName);
        }
    }
    

    然后在你的 People 类中:

    public sub Sort()
    
         PersonComparer pc = new PersonComparer()
    
        Array.Sort(_people, pc)
    
    end sub
    

    【讨论】:

    • 我已经走上了这条路,但从未弄清楚如何按除 FirstName 之外的其他属性进行排序。比如姓氏。
    • 好吧,如果你可以让它为FirstName 工作,那就表明你走在正确的道路上。也许你应该问一个单独的问题,如何让比较器使用多个字段(但实际上:在你问这个问题之前,试着在一张纸上弄清楚逻辑。这并不复杂!)。
    • ps.w.g 的回答似乎是实现您正在寻找的东西的好方法。
    【解决方案3】:

    你可以只添加一个Sort 方法:

    Public Sub Sort()
        _people = _people.OrderBy(Function(p) p.firstname).ToArray()
    End Sub
    
    Public Sub Sort(Of TKey)(keySelector As Func(Of Person, TKey))
        _people = _people.OrderBy(keySelector).ToArray()
    End Sub
    

    或者返回枚举数时排序:

    Public Function GetEnumerator() As IEnumerator(Of Person) _
            Implements IEnumerable(Of Person).GetEnumerator
        Return _people.OrderBy(Function(p) p.firstname).GetEnumerator()
    End Function
    

    【讨论】:

      猜你喜欢
      • 2018-06-30
      • 1970-01-01
      • 2017-12-31
      • 2014-10-14
      • 1970-01-01
      • 2016-05-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多