下面提供的代码示例工作正常,它正在做应该做的事情,但我并不满意。在VB.NET中寻找更智能的解决方案。结果的呈现(我的意思是每个小组的计数)非常尴尬。数据内容和记录列表等并不重要。此外,计数应按顺序排列{0},从{1}到{2},更多,然后是{3} ...先谢谢。
Dim Age1 As Integer = 5
Dim Age2 As Integer = 9
Dim myList As New List(Of Integer) = {1, 3, 5, 7, 9, 2, 4, 6, 8, 10, 2, 4, 5, 7, 8, 9, 6, 7, 9, 11}
Dim Lambda = myList.GroupBy(Function(x) New With {Key .Age1 = (x) < Age1,Key .Age2 = (x) > Age1 - 1 And (x) <= Age2,Key .Age3 = (x) > Age2}).ToList()
Dim group1, group2, group3 As Integer
myList = myList.OrderBy(Function(x) x).ToList()
Console.WriteLine(String.Join(",", myList.Select(Function(s) s.ToString).ToArray))
For Each group In Lambda
If group.Key.Age1 Then group1 = group.Count()
If group.Key.Age2 Then group2 = group.Count()
If group.Key.Age3 Then group3 = group.Count()
Next
' Obviously If Stop Then Error condition
If group1 + group2 + group3 <> myList.Count Then Stop
Console.WriteLine(String.Format("Groups: Less{0},From{1}To{2},MoreThan{3}", Age1, Age1, Age2 - 1, Age2))
Console.WriteLine(String.Format(" Age: {0,4},{1,8},{2,8}", group1, group2, group3))
'1,2,2,3,4,4,5,5,6,6,7,7,7,8,8,9,9,9,10,11
'Groups: Less5,From5To8,MoreThan9
'Age: 6, 12, 2
答案 0 :(得分:1)
以下是我将如何改进它:
Dim Age1 As Integer = 5
Dim Age2 As Integer = 9
Dim myList As New List(Of Integer) From {1, 3, 5, 7, 9, 2, 4, 6, 8, 10, 2, 4, 5, 7, 8, 9, 6, 7, 9, 11}
Console.WriteLine(String.Join(", ", myList.OrderBy(Function(x) x)))
console.WriteLine
Dim ageBins = myList.GroupBy(Function(age) If(age < Age1, 1, If(age >= Age1 And age <= Age2, 2, 3))) _
.Select(Function(agebin) New With { agebin.Key, .AgeCount = agebin.Count() }) _
.OrderBy(Function(agebin) agebin.Key)
For Each bin In ageBins
Dim msg As String
Select bin.Key
Case 1
msg = $"Less {Age1}"
Case 2
msg = $"From {Age1} To {Age2}"
Case Else
msg = $"MoreThan {Age2}"
End Select
Console.WriteLine($"{msg,12}: {bin.AgeCount}")
Next
您还可以更改代码以处理任意数量的分档:
Dim agesForBins = {5, 10}
Dim ageBins = myList.GroupBy(Function(age) Enumerable.Range(0, agesForBins.Length).Where(Function(n) age < agesForBins(n)).DefaultIfEmpty(agesForBins.Length).First) _
.Select(Function(agebin) New With { agebin.Key, .AgeCount = agebin.Count() }) _
.OrderBy(Function(agebin) agebin.Key)
For Each bin In ageBins
Dim msg As String
If bin.Key = 0 Then
msg = $"Less {agesForBins(0)}"
ElseIf bin.Key = agesForBins.Length Then
msg = $"MoreThan {agesForBins(bin.Key-1)-1}"
Else
msg = $"From {agesForBins(bin.Key-1)} To {agesForBins(bin.Key)-1}"
End If
Console.WriteLine($"{msg,12}: {bin.AgeCount}")
Next
答案 1 :(得分:1)
在我看来,这是最简单的方法:
Dim Age1 As Integer = 5
Dim Age2 As Integer = 9
Dim myList As New List(Of Integer) From {1, 3, 5, 7, 9, 2, 4, 6, 8, 10, 2, 4, 5, 7, 8, 9, 6, 7, 9, 11}
Dim group1 As Integer = myList.Where(Function (x) x < Age1).Count()
Dim group2 As Integer = myList.Where(Function (x) x > Age1 - 1 And x <= Age2).Count()
Dim group3 As Integer = myList.Where(Function (x) x > Age2).Count()
If group1 + group2 + group3 <> myList.Count Then Stop
Console.WriteLine(String.Format("Groups: Less{0},From{1}To{2},MoreThan{3}", Age1, Age1, Age2 - 1, Age2))
Console.WriteLine(String.Format(" Age: {0,4},{1,8},{2,8}", group1, group2, group3))
如果你想要一个基于LINQ的时髦方法,那么试试这个:
Dim bands() As Func(Of Integer, Boolean) = _
{ _
Function (x) x < Age1, _
Function (x) x <= Age2, _
Function (x) True _
}
Dim counts = _
myList _
.GroupBy(Function (x) Enumerable.Range(0, bands.Count).Where(Function (n) bands(n)(x)).First()) _
.Select(Function (x) x.Count()) _
.ToArray()
Dim group1 As Integer = counts(0)
Dim group2 As Integer = counts(1)
Dim group3 As Integer = counts(2)
答案 2 :(得分:0)
这是最快的2,我觉得很干净&#39;几个小时前发布的基于@Enigmativity概念的解决方案...关注他的n波段方法
Function simpleCSVsplit(ageForBins() As Integer, myList As List(Of Integer)) As List(Of Integer)
Dim Bands As New List(Of Integer)
For indx As Integer = 0 To ageForBins.Count - 1
Bands.Add(myList.Where(Function(x) x < ageForBins(indx)).Count())
myList = myList.Skip(Bands(indx)).ToList()
Next
Bands.Add(myList.Count)
Return Bands
End Function