我找到了这个文档( 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
与上述代码有关的两个疑问:
Parser
将元素插入数组的顺序是否fields
会保留给具有相同元素的元素order
?- 可以
printFields_Dic_Sort()
有不同的顺序printFields_Sort_Dic()
吗?(第一个转换然后排序;第二个排序然后转换为Dictionary
)
无法加入有关此的确切信息...谢谢
已编辑
添加了返回的类型Dictionary
好的,这就是问题所在:
- 如果我想让
KeyValuePair
(idx, obj) 不能使用array
(错误:这是可能的;挑战是如何在数组之间进行转换) - 我无法将排序存储
array
在 a 中,Dictionary
因为不能保证迭代它会给出有序values
(正确:通用字典不保证,见下文)。 - 有使用的选项
SortedDictionary
。但是,没有从array
to的直接转换SortedDictionary
(除非您进行迭代)...(**right*?*: no trivial conversion betweenarray
/list
andSortedDictionary
) - 然后,对于一个简单快捷的解决方案,它只保留使用
list
. 但是,也存在问题,因为它应该是KeyValuePair
我无法array
通过使用直接从 获取的列表toList
(错误:可以获取List (Of KeyValuePair (Of ...))
,但是,它需要先前的转换)。
所以根本没有优雅(简短而简单)的解决方案......(对:没有评论)
任何帮助将不胜感激(仍在使用它)-在下面解决...
编辑二
好的,这就是我最终所做的:通过使用array.ConvertAll
( msdn ) 并定义我自己的Converter
函数来解决第 4 点的问题...转换array
然后,List
从ToList
已经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