如何获取序列中的第一个和最后一个数字

How to get the first and last numbers in a sequence

我正在与 VBA 合作,尝试获取分隔数字序列中的第一个和最后一个数字。

数据仅显示为逗号分隔的数字序列。它们始终按数字升序排列。

所以这方面的一个例子可能是:

1,2,3,5,7,8,9

只需要第一个和最后一个序列,序列定义为比前一个数字多一个数字,在这种情况下有两个序列: 1,2,37,8,9。 5 不在序列中,因为它前后相隔不止一个(缺少 4 和 6)。

在这两种情况下,我需要每个序列的第一个和最后一个数字,即第一个序列的 1 & 3 和第二个序列的 7 & 9

我想知道正则表达式是否适用于此,或者将它们放入某个集合以便能够更轻松地向后和向前导航是否更好?

真的不确定从哪里开始 - 有什么想法吗?

非常感谢。

最简单的方法可能是使用 Split:

NumberSequence = "1,2,3,5,7,8,9"
ValueList = Split(NumberSequence, ",")

然后拉取 ValueList 数组中第一个和最后一个索引的值。

问题描述中的复杂之处在于识别数字序列中何时“缺失”数字,但 Split 也有助于解决此问题。将数字读入数组后,很容易遍历它们并确定“差距”在哪里。

这说明了方法:

Sub SampleProject()
    
    GetMinAndMax "1,2,3,5,7,8,9"

End Sub

Sub GetMinAndMax(NumberSequence As String)
    
    ValueList = Split(NumberSequence, ",")
    
    MinValue = CInt(ValueList(0))
    
    For i = 1 To UBound(ValueList)
        If CInt(ValueList(i)) > CInt(ValueList(i - 1)) + 1 Then
            MaxValue = CInt(ValueList(i - 1))
            
            'Ignore single numbers ("5" in your example)
            If Not MinValue = MaxValue Then MsgBox MinValue & " - " & MaxValue
            
            MinValue = CInt(ValueList(i))
            
        ElseIf i = UBound(ValueList) Then
            MaxValue = CInt(ValueList(UBound(ValueList)))
            MsgBox MinValue & " - " & MaxValue
            
        End If
    Next

End Sub

请尝试下一个功能:

Function SequenceMargins(s As String) As Variant
  Dim arr As Variant, i As Long, strSeq As String, firstEl As Long
  Dim arrFin As Variant, k As Long
  
  arr = Split(s, ",")
  ReDim arrFin(UBound(arr))

  For i = 0 To UBound(arr) - 1
    If CLng(arr(i)) = CLng(arr(i + 1)) - 1 And firstEl = 0 Then firstEl = CLng(arr(i))
    If firstEl <> 0 And CLng(arr(i)) > firstEl And CLng(arr(i)) <> CLng(arr(i + 1)) - 1 Then
        arrFin(k) = firstEl & "&" & arr(i): k = k + 1
        firstEl = 0
    End If
    If i = UBound(arr) - 1 And firstEl <> 0 Then
        arrFin(k) = firstEl & "&" & arr(UBound(arr)): k = k + 1
    End If
  Next i
  ReDim Preserve arrFin(k - 1)
  SequenceMargins = arrFin
End Function

可以这样调用:

Sub testSequenceMargins()
  Dim s As String, arr As Variant
  s = "1,2,3,5,7,8,9,10,13,14,15,20,34,35,36"
  arr = SequenceMargins(s)
  Debug.Print UBound(arr), arr(0), arr(UBound(arr))
End Sub

此方法采用包含数字序列的数组和 returns 包含找到的每个序列的第一个和最后一个数字的集合:

Option Explicit

Private Sub Form_Load()
   Dim c As Collection
   Set c = FirstAndLast(Array(1, 2, 3, 5, 7, 8, 9))
End Sub

Public Function FirstAndLast(ByVal Sequence As Variant) As Collection
   Dim i As Integer
   
   Set FirstAndLast = New Collection
   
   For i = LBound(Sequence) To UBound(Sequence) - 1
      If Sequence(i) + 1 = Sequence(i + 1) Then
         If FirstAndLast.Count Mod 2 = 0 Then FirstAndLast.Add Sequence(i)
         If i = UBound(Sequence) - 1 Then FirstAndLast.Add Sequence(i + 1)
      Else
         If FirstAndLast.Count Mod 2 = 1 Then FirstAndLast.Add Sequence(i)
      End If
   Next
End Function