1

我找到了这个文档( Enumerable.OrderBy(Of TSource, TKey) Method (IEnumerable(Of TSource), Func(Of TSource, TKey))),上面写着:

此方法执行稳定排序;也就是说,如果两个元素的键相等,则保留元素的顺序。相反,不稳定的排序不会保留具有相同键的元素的顺序。

但是,我对稳定排序和不稳定排序(?)之间的区别一无所知。

假设我有一个公共属性,一个名为fields( as clsField()) 的数组,其中 aparser放置了所有对象......

Public Class clsField
    Public idx As String
    Public name As String
    Public order As Long
End Class

Public Class Container
    Public fields As clsField()

    Public Function getFields() As Dictionary(Of String, clsField)
        If (fields Is Nothing) OrElse (fields.Count < 1) Then Return New Dictionary(Of String, clsField)
        Return fields.OrderBy(Function(fld) fld.order).ToDictionary(Of String, clsField)(Function(fld) fld.idx, Function(fld) fld)
    End Function

    Public Function getFields(blnAlternative As Boolean) As Dictionary(Of String, clsField)
        If (fields Is Nothing) OrElse (fields.Count < 1) Then Return New Dictionary(Of String, clsField)
        Return fields.ToDictionary(Of String, clsField)(Function(fld) fld.idx, Function(fld) fld).OrderBy(Function(pair) pair.Value.order)
    End Function
End Class

Public Class Consumer
    Public cont As Container
    Public parse As Parser

    Public Sub New(strFormat)
        cont = New Container
        cont.fields = parse.deserializeOject(Of clsField())(strFormat)
    End Sub

    Public Sub printFields_Sort_Dic()
        For Each fld As clsField In cont.getFields().Values
            Console.WriteLine(fld.ToString)
        Next
    End Sub

    Public Sub printFields_Dic_Sort()
        For Each fld As clsField In cont.getFields(True).Values
            Console.WriteLine(fld.ToString)
        Next
    End Sub

    Public Sub Main()
        printFields_Dic_Sort()
        printFields_Sort_Dic()
    End Sub
End Class

与上述代码有关的两个疑问:

  1. Parser将元素插入数组的顺序是否fields会保留给具有相同元素的元素order
  2. 可以printFields_Dic_Sort()有不同的顺序printFields_Sort_Dic()吗?(第一个转换然后排序;第二个排序然后转换为Dictionary

无法加入有关此的确切信息...谢谢

已编辑

添加了返回的类型Dictionary

好的,这就是问题所在:

  1. 如果我想让KeyValuePair(idx, obj) 不能使用array(错误:这是可能的;挑战是如何在数组之间进行转换)
  2. 我无法将排序存储array在 a 中,Dictionary因为不能保证迭代它会给出有序values正确:通用字典不保证,见下文)。
  3. 有使用的选项SortedDictionary。但是,没有从arrayto的直接转换SortedDictionary(除非您进行迭代)...(**right*?*: no trivial conversion between array/ listand SortedDictionary
  4. 然后,对于一个简单快捷的解决方案,它只保留使用list. 但是,也存在问题,因为它应该是KeyValuePair我无法array通过使用直接从 获取的列表toList错误:可以获取List (Of KeyValuePair (Of ...)),但是,它需要先前的转换)。

所以根本没有优雅(简短而简单)的解决方案......(:没有评论)

任何帮助将不胜感激(仍在使用它)-在下面解决...

编辑二

好的,这就是我最终所做的:通过使用array.ConvertAll( msdn ) 并定义我自己的Converter函数来解决第 4 点的问题...转换array然后,ListToList已经array将类型转换为(Of KeyValuePair (Of String, clsFld)). 希望它可以帮助别人:

'Imports System.Linq.Enumerable
'Imports System.Runtime.CompilerServices ' for extensions

Public Class clsField
    Public idx As String
    Public name As String
    Public weight As Long

    Public Sub New(Optional i As String = vbNullString, Optional n As String = vbNullString, Optional w As Long = vbNullString)
        idx = i : name = n : weight = w
    End Sub
End Class

Public Class Container
    Public fields As clsField()

    ' returns a list sorted by clsField.weight preserving order for elements with same 'weight' value
    Public Function getFields() As List(Of KeyValuePair(Of String, clsField))
        Dim auxList As List(Of KeyValuePair(Of String, clsField))

        If (fields Is Nothing) OrElse (fields.Count < 1) Then Return New List(Of KeyValuePair(Of String, clsField))
        ' .ToList to transform IEnumerable to the return type
        auxList = Array.ConvertAll(fields, New Converter(Of clsField, KeyValuePair(Of String, clsField))(AddressOf FieldToPair)).ToList
        Return auxList.OrderBy(Function(x) x.Value.weight).ToList()
    End Function

    Public Shared Function FieldToPair(fld As clsField) As KeyValuePair(Of String, clsField)
        Return New KeyValuePair(Of String, clsField)(fld.idx, fld)
    End Function
End Class

Public Class Consumer
    Public cont As Container

    Public Sub New()
        cont = New Container
        cont.fields.Add(New clsField("ffq", "foo30004", 33))
        cont.fields.Add(New clsField("ffc", "foo9997", 55))
        cont.fields.Add(New clsField("ffp", "foo9908", 55))
        cont.fields.Add(New clsField("ffo", "foo100001", 22))
        cont.fields.Add(New clsField("ffx", "foo8885", 33))
        cont.fields.Add(New clsField("ffz", "foo70002", 22))
        cont.fields.Add(New clsField("ffy", "foo8806", 33))
        cont.fields.Add(New clsField("ffa", "foo9009", 55))
        cont.fields.Add(New clsField("ffb", "foo8000", 55))
        cont.fields.Add(New clsField("ffn", "foo7003", 22))
    End Sub

    Public Sub printSortedFields()
        Dim aux As List(Of KeyValuePair(Of String, clsField))

        aux = cont.getFields()

        For Each pair As KeyValuePair(Of String, clsField) In aux
            Console.WriteLine(pair.Value.name)
            With pair.Value
                Debug.Print("name: " & .name & " || idx: " & .idx & " || weight: " & .weight)
            End With
        Next
    End Sub

    Public Sub Main()
        printSortedFields()
    End Sub
End Class

Module ArrayExtension ' custom method for array
    <Extension()>
    Public Sub Add(Of T)(ByRef arr As T(), item As T)
        If arr IsNot Nothing Then
            Array.Resize(arr, arr.Length + 1)
            arr(arr.Length - 1) = item
        Else
            ReDim arr(0)
            arr(0) = item
        End If

    End Sub
End Module

上述测试结果:

name: foo100001 || idx: ffo || weight: 22
name: foo70002 || idx: ffz || weight: 22
name: foo7003 || idx: ffn || weight: 22
name: foo30004 || idx: ffq || weight: 33
name: foo8885 || idx: ffx || weight: 33
name: foo8806 || idx: ffy || weight: 33
name: foo9997 || idx: ffc || weight: 55
name: foo9908 || idx: ffp || weight: 55
name: foo9009 || idx: ffa || weight: 55
name: foo8000 || idx: ffb || weight: 55
4

1 回答 1

1
  1. 稳定排序保留它们具有相同值的元素的顺序,所以是的,它们将按添加它们的相同顺序部分返回。但这并不重要,因为您稍后会将它们推送到字典中。见下文。

  2. Dictionary<TKey, TValue>不定义排序并且可能不保留元素 l 的顺序。因为那printFields_Sort_Dic()可能会以不同的顺序返回它们。

于 2017-02-12T23:54:21.670 回答