Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

Finding if Numbers are ranges

Posted on 2016-10-07
8
Medium Priority
?
64 Views
Last Modified: 2016-10-10
I am having the need to determine if numbers read from a database are sequential, in my case its phone numbers


So i will pass the following numbers

5125551122
5125551130
5125551131
5125551132
5125551140

What i want to create as an output is something like that

5125551122
5125551130 - 5125551132
5125551140
0
Comment
Question by:AlexPonnath
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 4
  • 3
8 Comments
 
LVL 34

Expert Comment

by:it_saige
ID: 41834195
What determines the grouping?  Consider the following:
5125551122
5125551123
5125551124
5125551125
5125551126
5125551127
5125551128
5125551129
5125551130
5125551131
5125551132
5125551140

Open in new window


Would you expect the output to be -
5125551122 - 5125551132
5125551140

Open in new window

Or
5125551122 - 5125551129
5125551130 - 5125551132
5125551140

Open in new window


-saige-
0
 

Author Comment

by:AlexPonnath
ID: 41834270
The below is what I would want to output

5125551122 - 5125551132
5125551140
0
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 

Author Comment

by:AlexPonnath
ID: 41834407
The SQL Data Island is not an options since the Data comes from a text file and there is no SQL Server for this app
0
 
LVL 34

Expert Comment

by:it_saige
ID: 41834465
See if this doesn't do the trick for you:
Module Module1
	Sub Main()
		Dim phoneNumbers = New List(Of String) From {"5125551122", "5125551123", "5125551124", "5125551125", "5125551126", "5125551127", "5125551128", "5125551129", "5125551130", "5125551131", "5125551132", "5125551140"}
		phoneNumbers = phoneNumbers.OrderBy(Function(x) x).ToList()
		Dim results = String.Join(Environment.NewLine, phoneNumbers.GroupAdjacentBy(Function(x, y) (Convert.ToInt64(x) + 1).ToString(String.Format("D{0}", x.Length)) = y).Select(Function(g) New List(Of String)() From {g.First(), g.Last()}.Distinct()).Select(Function(g) String.Join(" - ", g)))
		Console.WriteLine(results)
		Console.ReadLine()
	End Sub
End Module

Module Extensions
	<System.Runtime.CompilerServices.Extension()> _
	Public Iterator Function GroupAdjacentBy(Of T)(source As IEnumerable(Of T), predicate As Func(Of T, T, Boolean)) As IEnumerable(Of IEnumerable(Of T))
		Using e = source.GetEnumerator()
			If e.MoveNext() Then
				Dim list = New List(Of T)() From {e.Current}
				Dim pred = e.Current
				While e.MoveNext()
					If predicate(pred, e.Current) Then
						list.Add(e.Current)
					Else
						Yield list
						list = New List(Of T)() From {e.Current}
					End If
					pred = e.Current
				End While
				Yield list
			End If
		End Using
	End Function
End Module

Open in new window


Which produces the following output -Capture.JPG
-saige-
0
 
LVL 34

Expert Comment

by:it_saige
ID: 41834468
And just tested your original list of numbers:
Module Module1
	Sub Main()
		Dim phoneNumbers = New List(Of String) From {"5125551122", "5125551130", "5125551131", "5125551132", "5125551140"}
		phoneNumbers = phoneNumbers.OrderBy(Function(x) x).ToList()
		Dim results = String.Join(Environment.NewLine, phoneNumbers.GroupAdjacentBy(Function(x, y) (Convert.ToInt64(x) + 1).ToString(String.Format("D{0}", x.Length)) = y).Select(Function(g) New List(Of String)() From {g.First(), g.Last()}.Distinct()).Select(Function(g) String.Join(" - ", g)))
		Console.WriteLine(results)
		Console.ReadLine()
	End Sub
End Module

Module Extensions
	<System.Runtime.CompilerServices.Extension()> _
	Public Iterator Function GroupAdjacentBy(Of T)(source As IEnumerable(Of T), predicate As Func(Of T, T, Boolean)) As IEnumerable(Of IEnumerable(Of T))
		Using e = source.GetEnumerator()
			If e.MoveNext() Then
				Dim list = New List(Of T)() From {e.Current}
				Dim pred = e.Current
				While e.MoveNext()
					If predicate(pred, e.Current) Then
						list.Add(e.Current)
					Else
						Yield list
						list = New List(Of T)() From {e.Current}
					End If
					pred = e.Current
				End While
				Yield list
			End If
		End Using
	End Function
End Module

Open in new window

Produces the following output -Capture.JPG
-saige-
0
 

Author Comment

by:AlexPonnath
ID: 41834498
Yes the console app does work, is there a way you can provide the code for a non console app like a function to which i can just pass one nbr after the other ? My code loops thru a List() which has the nbrs
and i want to be able to get the output as list which i can then loop thru
0
 
LVL 34

Accepted Solution

by:
it_saige earned 2000 total points
ID: 41837036
The example provided is not specific to any implementation and therefore can be used for any vb.net project.  If you need a method that performs the task then here you go:
Module Extensions
	<System.Runtime.CompilerServices.Extension()> _
	Public Function PhoneGroups(source As IEnumerable(Of String)) As IEnumerable(Of String)
		Return source.OrderBy(Function(x) x).GroupAdjacentBy(Function(x, y) (Convert.ToInt64(x) + 1).ToString(String.Format("D{0}", x.Length)) = y).Select(Function(g) New List(Of String)() From {g.First(), g.Last()}.Distinct()).Select(Function(g) String.Join(" - ", g))
	End Function

	<System.Runtime.CompilerServices.Extension()> _
	Public Iterator Function GroupAdjacentBy(Of T)(source As IEnumerable(Of T), predicate As Func(Of T, T, Boolean)) As IEnumerable(Of IEnumerable(Of T))
		Using e = source.GetEnumerator()
			If e.MoveNext() Then
				Dim list = New List(Of T)() From {e.Current}
				Dim pred = e.Current
				While e.MoveNext()
					If predicate(pred, e.Current) Then
						list.Add(e.Current)
					Else
						Yield list
						list = New List(Of T)() From {e.Current}
					End If
					pred = e.Current
				End While
				Yield list
			End If
		End Using
	End Function
End Module

Open in new window


Example usage:

Console Implementation -
Module Module1
	Sub Main()
		Dim phoneNumbers = New List(Of String) From {"5125551122", "5125551130", "5125551131", "5125551132", "5125551140"}
		For Each group In phoneNumbers.PhoneGroups()
			Console.WriteLine(group)
		Next
		Console.ReadLine()
	End Sub
End Module

Module Extensions
	<System.Runtime.CompilerServices.Extension()> _
	Public Function PhoneGroups(source As IEnumerable(Of String)) As IEnumerable(Of String)
		Return source.OrderBy(Function(x) x).GroupAdjacentBy(Function(x, y) (Convert.ToInt64(x) + 1).ToString(String.Format("D{0}", x.Length)) = y).Select(Function(g) New List(Of String)() From {g.First(), g.Last()}.Distinct()).Select(Function(g) String.Join(" - ", g))
	End Function

	<System.Runtime.CompilerServices.Extension()> _
	Public Iterator Function GroupAdjacentBy(Of T)(source As IEnumerable(Of T), predicate As Func(Of T, T, Boolean)) As IEnumerable(Of IEnumerable(Of T))
		Using e = source.GetEnumerator()
			If e.MoveNext() Then
				Dim list = New List(Of T)() From {e.Current}
				Dim pred = e.Current
				While e.MoveNext()
					If predicate(pred, e.Current) Then
						list.Add(e.Current)
					Else
						Yield list
						list = New List(Of T)() From {e.Current}
					End If
					pred = e.Current
				End While
				Yield list
			End If
		End Using
	End Function
End Module

Open in new window


Produces the following output -Capture.JPG
Windows Forms implementation -

Form1.vb -
Public Class Form1
	ReadOnly phoneNumbers As New List(Of String) From {"5125551122", "5125551130", "5125551131", "5125551132", "5125551140"}

	Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
		ListBox1.DataSource = phoneNumbers.PhoneGroups().ToList()
	End Sub
End Class

Module Extensions
	<System.Runtime.CompilerServices.Extension()> _
	Public Function PhoneGroups(source As IEnumerable(Of String)) As IEnumerable(Of String)
		Return source.OrderBy(Function(x) x).GroupAdjacentBy(Function(x, y) (Convert.ToInt64(x) + 1).ToString(String.Format("D{0}", x.Length)) = y).Select(Function(g) New List(Of String)() From {g.First(), g.Last()}.Distinct()).Select(Function(g) String.Join(" - ", g))
	End Function

	<System.Runtime.CompilerServices.Extension()> _
	Public Iterator Function GroupAdjacentBy(Of T)(source As IEnumerable(Of T), predicate As Func(Of T, T, Boolean)) As IEnumerable(Of IEnumerable(Of T))
		Using e = source.GetEnumerator()
			If e.MoveNext() Then
				Dim list = New List(Of T)() From {e.Current}
				Dim pred = e.Current
				While e.MoveNext()
					If predicate(pred, e.Current) Then
						list.Add(e.Current)
					Else
						Yield list
						list = New List(Of T)() From {e.Current}
					End If
					pred = e.Current
				End While
				Yield list
			End If
		End Using
	End Function
End Module

Open in new window

Form1.Designer.vb -
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Partial Class Form1
    Inherits System.Windows.Forms.Form

    'Form overrides dispose to clean up the component list.
    <System.Diagnostics.DebuggerNonUserCode()> _
    Protected Overrides Sub Dispose(ByVal disposing As Boolean)
        Try
            If disposing AndAlso components IsNot Nothing Then
                components.Dispose()
            End If
        Finally
            MyBase.Dispose(disposing)
        End Try
    End Sub

    'Required by the Windows Form Designer
    Private components As System.ComponentModel.IContainer

    'NOTE: The following procedure is required by the Windows Form Designer
    'It can be modified using the Windows Form Designer.  
    'Do not modify it using the code editor.
    <System.Diagnostics.DebuggerStepThrough()> _
    Private Sub InitializeComponent()
		Me.ListBox1 = New System.Windows.Forms.ListBox()
		Me.SuspendLayout()
		'
		'ListBox1
		'
		Me.ListBox1.FormattingEnabled = True
		Me.ListBox1.Location = New System.Drawing.Point(13, 13)
		Me.ListBox1.Name = "ListBox1"
		Me.ListBox1.Size = New System.Drawing.Size(259, 95)
		Me.ListBox1.TabIndex = 0
		'
		'Form1
		'
		Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
		Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
		Me.ClientSize = New System.Drawing.Size(284, 123)
		Me.Controls.Add(Me.ListBox1)
		Me.Name = "Form1"
		Me.Text = "Form1"
		Me.ResumeLayout(False)

	End Sub
	Friend WithEvents ListBox1 As System.Windows.Forms.ListBox

End Class

Open in new window


Produces the following output -Capture.JPG
ASP.NET implementation -

Default.aspx -
<%@ Page Title="Home Page" Language="VB" AutoEventWireup="true" CodeBehind="Default.aspx.vb" Inherits="EE_Q28975079_ASP._Default" %>
<form id="form1" runat="server">
	<asp:ListBox ID="ListBox1" runat="server" Height="99px" Width="250px"></asp:ListBox>
</form>

Open in new window

Default.aspx.vb -
Public Class _Default
	Inherits Page
	ReadOnly phoneNumbers As New List(Of String) From {"5125551122", "5125551130", "5125551131", "5125551132", "5125551140"}

	Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load
		ListBox1.DataSource = phoneNumbers.PhoneGroups().ToList()
		ListBox1.DataBind()
	End Sub
End Class

Module Extensions
	<System.Runtime.CompilerServices.Extension()> _
	Public Function PhoneGroups(source As IEnumerable(Of String)) As IEnumerable(Of String)
		Return source.OrderBy(Function(x) x).GroupAdjacentBy(Function(x, y) (Convert.ToInt64(x) + 1).ToString(String.Format("D{0}", x.Length)) = y).Select(Function(g) New List(Of String)() From {g.First(), g.Last()}.Distinct()).Select(Function(g) String.Join(" - ", g))
	End Function

	<System.Runtime.CompilerServices.Extension()> _
	Public Iterator Function GroupAdjacentBy(Of T)(source As IEnumerable(Of T), predicate As Func(Of T, T, Boolean)) As IEnumerable(Of IEnumerable(Of T))
		Using e = source.GetEnumerator()
			If e.MoveNext() Then
				Dim list = New List(Of T)() From {e.Current}
				Dim pred = e.Current
				While e.MoveNext()
					If predicate(pred, e.Current) Then
						list.Add(e.Current)
					Else
						Yield list
						list = New List(Of T)() From {e.Current}
					End If
					pred = e.Current
				End While
				Yield list
			End If
		End Using
	End Function
End Module

Open in new window

Default.aspx.designer.vb -
'------------------------------------------------------------------------------
' <auto-generated>
'     This code was generated by a tool.
'
'     Changes to this file may cause incorrect behavior and will be lost if
'     the code is regenerated. 
' </auto-generated>
'------------------------------------------------------------------------------

Option Strict On
Option Explicit On


Partial Public Class _Default

	'''<summary>
	'''form1 control.
	'''</summary>
	'''<remarks>
	'''Auto-generated field.
	'''To modify move field declaration from designer file to code-behind file.
	'''</remarks>
	Protected WithEvents form1 As Global.System.Web.UI.HtmlControls.HtmlForm

	'''<summary>
	'''ListBox1 control.
	'''</summary>
	'''<remarks>
	'''Auto-generated field.
	'''To modify move field declaration from designer file to code-behind file.
	'''</remarks>
	Protected WithEvents ListBox1 As Global.System.Web.UI.WebControls.ListBox
End Class

Open in new window


Produces the following output -Capture.JPG
-saige-
0

Featured Post

Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Well, all of us have seen the multiple EXCEL.EXE's in task manager that won't die even if you call the .close, .dispose methods. Try this method to kill any excels in memory. You can copy the kill function to create a check function and replace the …
Creating an analog clock UserControl seems fairly straight forward.  It is, after all, essentially just a circle with several lines in it!  Two common approaches for rendering an analog clock typically involve either manually calculating points with…
Do you want to know how to make a graph with Microsoft Access? First, create a query with the data for the chart. Then make a blank form and add a chart control. This video also shows how to change what data is displayed on the graph as well as form…
Have you created a query with information for a calendar? ... and then, abra-cadabra, the calendar is done?! I am going to show you how to make that happen. Visualize your data!  ... really see it To use the code to create a calendar from a q…

704 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question