
Aug 16th, 2019, 08:20 AM
#1
Thread Starter
Lively Member
[RESOLVED] String of Numbers to Range of Numbers
Hi, I am hoping someone can help with this or point me in the right direction. I have tried searching the site but could not find anything similar and didn't know exactly how to search this. So I apologize if this has been discussed/answered already.
I have a sub that will generate a string of numbers separated by a comma. I would like a function that will combine the numbers into ranges of numbers with a hyphen. Ex:
Generated from sub:
501510, 1232, 1233, 1234, 367, 366, 365, 5052, 893, 897, 1104
Function Output:
5052, 365367, 501510, 893, 897, 1104, 12321234
The original numbers and combination (Generated from Sub) could be any amount of numbers and in any combination. The number will always be whole numbers and always positive. The function should put them in an order like the Function output numbers above.
I hope this makes sense, Thank you.

Aug 16th, 2019, 08:42 AM
#2
Re: String of Numbers to Range of Numbers
You can use stringVariable.Split() to convert the string into an array of strings (use "," as the separator).
One way would be to make a boolean array which has enough elements for all of the numbers (so for your example data, the array would have an upperbound of at least 1234).
Once you have that, read thru the items and set the boolean values in the array to True when a single value is found (so for 1232 set booleanArray(1232)=True ), and for ranges use a For loop to set the values to True.
When that is done you can loop the boolean array to find items that are set, and build the string accordingly. When you find a True in the array, that number should be part of the output  but if the next item is also true you need to display a range.
Of course it would be easier if the original sub generated the boolean array instead (or even better a List(Of Integer) ), but that might not be viable in your circumstances.

Aug 16th, 2019, 08:54 AM
#3
Thread Starter
Lively Member
Re: String of Numbers to Range of Numbers
You can use stringVariable.Split() to convert the string into an array of strings (use "," as the separator). OK I understand and can do this.
One way would be to make a boolean array which has enough elements for all of the numbers (so for your example data, the array would have an upperbound of at least 1234). I have never worked with boolean arrays before. I understand the concept and what you are saying just wouldn't know how to initiate.
Once you have that, read thru the items and set the boolean values in the array to True when a single value is found (so for 1232 set booleanArray(1232)=True ), and for ranges use a For loop to set the values to True. Makes sense but again would not know how to initiate.
When that is done you can loop the boolean array to find items that are set, and build the string accordingly. When you find a True in the array, that number should be part of the output  but if the next item is also true you need to display a range. OK, I understand the concept and what you are saying but again..
Of course it would be easier if the original sub generated the boolean array instead (or even better a List(Of Integer) ), but that might not be viable in your circumstances. I could convert the string to List(of Integer) before sending to the function if that truly would make it easier. I do not believe that it will affect the sub in anyway.

Aug 16th, 2019, 09:08 AM
#4
Re: String of Numbers to Range of Numbers
Converting from strings to numbers is mandatory in order to build the output you want (without it, you wouldn't be able to get 365367), it's just a matter of where that conversion happens.
After I posted I realised that just using a List(of Integer) would be best, as it simplifies the design and probably memory usage too.
When you have the source items Split, you can add them to the list  for a single number just add the number, if it is a range like 501510 then use a For loop to add all the items in the range.
You can then sort the list, and build the output string you want based on the items in it. If the next number is one higher than the current number then they are both part of a range, otherwise the current number is just a single number (or the end of a range). Use appropriate variables to determine if you are currently in a range, and which number the range started with.

Aug 16th, 2019, 11:12 AM
#5
Thread Starter
Lively Member
Re: String of Numbers to Range of Numbers
OK, so I got it working. I think I did it the way you explained. I took a two prong approach using two separate functions. If this could be simplified I would love to know how. The first function will get all the numbers like you suggested, split the ranges, and put them in acceding order.
The second function will then take the sorted numbers and place them back into a ranged format. I then, back in the sub, take the new list and join to a new string.
Get the Point Numbers, separate and place in order:
Code:
Public Function ToSortedListOfPointNumbers(ByVal pointNumbers As String)
Dim pointNumberList As New List(Of Integer)
For Each pointNumber As String In pointNumbers.Split(","c)
If pointNumber.Contains(""c) Then
Dim firstNumber As Integer = Convert.ToInt32(pointNumber.Split(""c)(0))
Dim lastNumber As Integer = Convert.ToInt32(pointNumber.Split(""c)(1))
For pn As Integer = firstNumber To lastNumber
pointNumberList.Add(pn)
Next
Else
pointNumberList.Add(Convert.ToInt32(pointNumber))
End If
Next
Dim sortedPointNumberList As List(Of Integer) = pointNumberList.OrderBy(Function(number) number).ToList()
Return sortedPointNumberList
End Function
Take Sorted Point Numbers and place into ranged groups
Code:
Function ToRangesOfPointNumbers(ByVal sortedPointNumberList As List(Of Integer)) As String()
If sortedPointNumberList.Count < 1 Then Return New String() {}
Dim numberOfPoints = sortedPointNumberList.Count
Dim startNumbers = New List(Of Integer)()
Dim endNumbers = New List(Of Integer)()
For i = 0 To numberOfPoints  1  1
If i = 0 Then startNumbers.Add(sortedPointNumberList(0))
If sortedPointNumberList(i + 1) > sortedPointNumberList(i) + 1 Then
endNumbers.Add(sortedPointNumberList(i))
startNumbers.Add(sortedPointNumberList(i + 1))
End If
Next
endNumbers.Add(sortedPointNumberList(numberOfPoints  1))
Return Enumerable.Range(0, endNumbers.Count).[Select](Function(i) startNumbers(i).ToString() + (If(endNumbers(i) = startNumbers(i), "", "" & endNumbers(i).ToString()))).ToArray()
End Function
In sub to final result of updatedIncludedPointNumbers
Code:
Dim sortedPointNumbers = ToSortedListOfPointNumbers(includedNumbers & "," & cogoPointsToAdd)
Dim rangedPointNumbers = ToRangesOfPointNumbers(sortedPointNumbers)
Dim updatedIncludedPointNumbers As String = String.Join(",", rangedPointNumbers.ToArray)
What do you think? I feel this could be simplified, but I have tunnel vision now and cant seem to see it. I will play with it over the weekend but any pointers or suggestions are very welcome.

Aug 16th, 2019, 12:51 PM
#6
Re: [RESOLVED] String of Numbers to Range of Numbers
That looks good
In ToSortedListOfPointNumbers, I would change this section:
Code:
Dim firstNumber As Integer = Convert.ToInt32(pointNumber.Split(""c)(0))
Dim lastNumber As Integer = Convert.ToInt32(pointNumber.Split(""c)(1))
For pn As Integer = firstNumber To lastNumber
...to:
Code:
Dim rangeNumbers As String = pointNumber.Split(""c)
For pn As Integer = Convert.ToInt32(rangeNumbers(0)) To Convert.ToInt32(rangeNumbers(1))
This should run slightly faster (as the complex split only happens once), and takes a little less code.
Note however that this section won't cope with negative numbers (due to the  character), so will need some extra work if you think you might ever need to deal with them.
In ToRangesOfPointNumbers I would change this:
Code:
For i = 0 To numberOfPoints  1  1
If i = 0 Then startNumbers.Add(sortedPointNumberList(0))
to:
Code:
startNumbers.Add(sortedPointNumberList(0))
For i = 0 To numberOfPoints  1  1
...because you have already checked that sortedPointNumberList contains at least one item.
There isn't really much scope to simplify these routines, but if you could modify the original sub the data comes from (so that it returns a List(of Integer)) then that would simplify the process as it would reduce ToSortedListOfPointNumbers to just the OrderBy line.

Aug 16th, 2019, 12:59 PM
#7
Thread Starter
Lively Member
Re: [RESOLVED] String of Numbers to Range of Numbers
Thank so much! I got a little help from "the great white box of hope" (Google). Once you explained how to approach it, it was easier to search for what I was looking for. I will defiantly be incorporating your suggestions. And there should never be negative numbers as these represent survey point numbers which are always positive. So I should be good. (Famous last words)
Thank you again so much!!
Posting Permissions
 You may not post new threads
 You may not post replies
 You may not post attachments
 You may not edit your posts

Forum Rules

Click Here to Expand Forum to Full Width
