Jump to content

How to parse range


xoraxax
 Share

Recommended Posts

Hm. I mean a different thing

For example

We have a form:

Range: __InputRange___

Value: __inputValue___

 

User input: inputRange="5,9,10-15", Value=7

And i need to evaluate that 7 is not in the range "5,9,10-15". But 12 (for example) is in that range.

So i need to parse the range string to array or something and check if Value is in that array or not.

Link to comment
Share on other sites

  • Moderators

xoraxax,

This is a function that I developed to parse positive ranges:

#include <MsgBoxConstants.au3>

$sRet = _Expand_Range("5-7,9,10-15", ",")

MsgBox($MB_SYSTEMMODAL, "Expanded", $sRet)


Func _Expand_Range($vRange, $sDelim = ";")

    Local $iNumber, $aSplit_2
    If $sDelim = Default Then $sDelim = ";"
    $vRange = StringStripWS($vRange, 8)
    $aSplit_1 = StringSplit($vRange, $sDelim)
    $vRange = ""
    For $i = 1 To $aSplit_1[0]
        ; Check for correct range syntax
        If Not StringRegExp($aSplit_1[$i], "^\d+(-\d+)?$") Then Return SetError(3, 0, -1)
        $aSplit_2 = StringSplit($aSplit_1[$i], "-")
        Switch $aSplit_2[0]
            Case 1
                $vRange &= $aSplit_2[1] & $sDelim
            Case 2
                If Number($aSplit_2[2]) >= Number($aSplit_2[1]) Then
                    $iNumber = $aSplit_2[1] - 1
                    Do
                        $iNumber += 1
                        $vRange &= $iNumber & $sDelim
                    Until $iNumber = $aSplit_2[2]
                EndIf
        EndSwitch
    Next

    Return StringTrimRight($vRange, 1)
EndFunc   ;==>_Expand_Range
I hope it is useful. :)

M23

Edited by Melba23
Typo

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to comment
Share on other sites

Here is my Func, in case someone want it. 

func isInRange($range,$value)
dim $trunk[29]
for $t In $trunk
    $t=0
next

$range_sp=StringSplit($range,",")
for $i=1 to $range_sp[0]
    if StringInStr($range_sp[$i],"-")=0 Then
        $trunk[$range_sp[$i]]=1
    Else
        $r_sp=StringSplit($range_sp[$i],"-")
        if $r_sp[0]<>2 then
            MsgBox(0,0,"Неверно указан диапазон")
            Exit
        EndIf
        if int($r_sp[1])>int($r_sp[2]) Then
            MsgBox(0,0,"Неверно указан диапазон")
            Exit
        EndIf
        for $ii=$r_sp[1] to $r_sp[2]
            $trunk[$ii]=1
        Next
    EndIf
Next
if $trunk[int($value)]=1 then
        return 1
    Else
        return 0
    EndIf
EndFunc
Link to comment
Share on other sites

you are building an array with as many elements as the full range and then set to 1 only the elements of the array corresponding with values in your range.
then you check if an array element contains 0 or 1 to see if that number is within your range.

... seems a not much optimized way

I suggest to have a look to> this function by Mat

in this case could be used in this way:

(modified separator from ";" to ",")

#include <Array.au3>
#include <Constants.au3>

Local $aMyRange = _Range_Parse("5,9,10-15") ; your ranges
Local $Value = 4 ; value to check if is inside

MsgBox(0, "in range?", _Range_Contains($aMyRange, $Value) & @CRLF)


Func _Range_Parse($sRange)
    Local $aRegions = StringSplit($sRange, ","), $aBounds
    Local $aRet[$aRegions[0] + 1][2]
    $aRet[0][0] = $aRegions[0]

    For $i = 1 To $aRegions[0]

        If StringIsFloat($aRegions[$i]) Or StringIsInt($aRegions[$i]) Then ; Just a single number
            $aRet[$i][0] = Number($aRegions[$i])
            $aRet[$i][1] = Number($aRegions[$i])
        Else
            $aBounds = StringRegExp($aRegions[$i], "(-?\d+(?:\.\d+)?)\-(-?\d+(?:\.\d+)?)", 3)

            If UBound($aBounds) <> 2 Then Return SetError(1, 0, 0)

            $aRet[$i][0] = Number($aBounds[0])
            $aRet[$i][1] = Number($aBounds[1])
        EndIf
    Next

    _Range_Normalize($aRet)

    Return $aRet
EndFunc   ;==>_Range_Parse

Func _Range_Normalize(ByRef $aRange)
    If Not IsArray($aRange) Then Return SetError(1, 0, 0)

    ; Sort the array by region lower bounds
    _ArraySort($aRange, 0, 1)

    ; Check for overlapping regions

    Local $i = 0
    While $i < $aRange[0][0] - 1
        $i += 1

        If $aRange[$i][1] >= $aRange[$i + 1][0] Then ; Regions Overlap
            If $aRange[$i + 1][1] > $aRange[$i][1] Then $aRange[$i][1] = $aRange[$i + 1][1]
            _ArrayDelete($aRange, $i + 1)
            $aRange[0][0] -= 1
            $i -= 1
        EndIf
    WEnd

    Return 1
EndFunc   ;==>_Range_Normalize

; Could be replaced by a binary search, but $aRange is expected to contain very few (<10) elements
Func _Range_Contains(ByRef Const $aRange, $nNeedle)

    If Not IsArray($aRange) Then Return SetError(1, 0, 0)

    For $i = 1 To $aRange[0][0]
        If $nNeedle < $aRange[$i][0] Then Return False
        If $nNeedle <= $aRange[$i][1] Then Return True
    Next

    Return False
EndFunc   ;==>_Range_Contains

Func _Range_ToString(ByRef Const $aRange)
    If Not IsArray($aRange) Then Return SetError(1, 0, 0)

    Local $sRet = ""

    For $i = 1 To $aRange[0][0]
        If $aRange[$i][0] = $aRange[$i][1] Then
            $sRet &= $aRange[$i][0] & ";"
        Else
            $sRet &= $aRange[$i][0] & "-" & $aRange[$i][1] & ";"
        EndIf
    Next

    $sRet = StringTrimRight($sRet, 1)

    Return $sRet
EndFunc   ;==>_Range_ToString

 

image.jpeg.9f1a974c98e9f77d824b358729b089b0.jpeg Chimp

small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt....

Link to comment
Share on other sites

#include <Array.au3>
#include <Constants.au3>

$Res = _Belongs("5,9,4-15,6, 22-88,1", '6')
MsgBox(0, '@error = ' & @error, 'Belongs? = ' & $Res)
; MsgBox(0, "in range?", $f)

Func _Belongs($sRange, $sNum)
    $sRange = StringStripWS($sRange & ',', 8) ; Удаляем все пробелы
    ; $sRange = StringRegExpReplace($sRange, '[^\d,-]', '')
    If StringRegExp($sRange, '[^\d,-]') Or StringRegExp($sRange, '[,-]{2,}') Then Return SetError(2, 0, -2) ; вылет с ошибкой если существуют иные символы

    ; флаг=1, используется смещение для пошагового поиска всех элементов
    $iOffset = 1
    $iStart = 1
    $iEnd = 1
    While 1
        $aRes = StringRegExp($sRange, '[,-]', 1, $iOffset)
        If @error Then ExitLoop ; Выход из цикла если более не найдено
        $iOffset = @extended ; Сохраняет позицию, от которой начать следующий поиск
        $iStart = $iEnd
        $iEnd = $iOffset
        Switch $aRes[0]
            Case ','
                ; MsgBox(0, 'Сообщение', StringMid($sRange, $iStart, $iEnd-$iStart-1))
                If StringMid($sRange, $iStart, $iEnd - $iStart - 1) = $sNum Then Return SetError(0, 0, 1)
            Case '-'
                $sNum1 = Number(StringMid($sRange, $iStart, $iEnd - $iStart - 1))
                ; MsgBox(0, 'sNum1', $sNum1)
                $aRes = StringRegExp($sRange, '[,-]', 1, $iOffset)
                If @error Then ExitLoop
                $iOffset = @extended ; Сохраняет позицию, от которой начать следующий поиск
                If $aRes[0] = '-' Then Return SetError(3, 0, -3) ; вылет с ошибкой если повтор интерпретации диапазона
                $iStart = $iEnd
                $iEnd = $iOffset
                $sNum2 = Number(StringMid($sRange, $iStart, $iEnd - $iStart - 1))
                ; MsgBox(0, 'sNum2', $sNum2)
                ; If $sNum < $sNum1 Or $sNum > $sNum2 Then
                If $sNum >= $sNum1 And $sNum <= $sNum2 Then Return SetError(0, 0, 1)
        EndSwitch
    WEnd

    Return SetError(0, 0, 0)
EndFunc   ;==>_Belongs

Link to comment
Share on other sites

$sRange = "1,3,5-8,12-18,22,25"
$dValue = 7

$q = Inside2($sRange, $dValue)
ConsoleWrite($q&@CRLF)

Func Inside2($sRange, $dValue)
    Local $aRange, $i

    $aRange = StringSplit($sRange,";,")
    For $i = 1 To $aRange[0]
        $aRangeP = StringRegExp($aRange[$i],"(\d+)",3)
        Switch UBound($aRangeP)
            Case 1
                If $dValue = Number($aRangeP[0]) Then Return True
            Case 2
                If Number($aRangeP[1]) > $dValue And $dValue > Number($aRangeP[0]) Then Return True
        EndSwitch
    Next
    Return False
EndFunc

Link to comment
Share on other sites

Local $value = 7 ; 12 ;
Local $range = "5,9,10-15,17"

Local $Res = _IsInRange($range, $value)
MsgBox(0, 'Result', 'Belongs? = ' & $Res)


Func _IsInRange($iRange, $iValue)
    Local $iRange2 = Execute("'" & StringRegExpReplace(StringStripWS($iRange, 8), "(\d+)-(\d+)", "'& __Expand($1,$2) & '") & "'")
    ;ConsoleWrite($iRange2 & @LF)
    Return StringRegExp($iRange2, "(^|,)" & $iValue & "(,|$)") ; If $iValue matches any values in $iRange2, then returns 1, else returns 0.
EndFunc   ;==>_IsInRange

;Internal function.
Func __Expand($Start, $End)
    Local $sRet
    For $i = $Start To $End
        $sRet &= $i & ","
    Next
    Return StringTrimRight($sRet, 1)
EndFunc   ;==>__Expand

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...