Solved

Finding if Numbers are ranges

Posted on 2016-10-07
8
57 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
SharePoint Admin?

Enable Your Employees To Focus On The Core With Intuitive Onscreen Guidance That is With You At The Moment of Need.

 

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 500 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

[Webinar] How Hackers Steal Your Credentials

Do You Know How Hackers Steal Your Credentials? Join us and Skyport Systems to learn how hackers steal your credentials and why Active Directory must be secure to stop them. Thursday, July 13, 2017 10:00 A.M. PDT

Question has a verified solution.

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

Introduction As chip makers focus on adding processor cores over increasing clock speed, developers need to utilize the features of modern CPUs.  One of the ways we can do this is by implementing parallel algorithms in our software.   One recent…
Parsing a CSV file is a task that we are confronted with regularly, and although there are a vast number of means to do this, as a newbie, the field can be confusing and the tools can seem complex. A simple solution to parsing a customized CSV fi…
Monitoring a network: why having a policy is the best policy? Michael Kulchisky, MCSE, MCSA, MCP, VTSP, VSP, CCSP outlines the enormous benefits of having a policy-based approach when monitoring medium and large networks. Software utilized in this v…
Michael from AdRem Software explains how to view the most utilized and worst performing nodes in your network, by accessing the Top Charts view in NetCrunch network monitor (https://www.adremsoft.com/). Top Charts is a view in which you can set seve…
Suggested Courses

615 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