Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>If we assume that the start and end ranges will follow the same alternating pattern, and limit the range of digits to <code>0-9</code> and <code>A-Z</code>, we can think of each group of digits as a component in a multi-dimensonal coordinate. For example, <code>1A</code> would correspond to the two-dimensional coordinate <code>(1,A)</code> (which is what Excel uses to label its two-dimensional grid of rows and columns); whereas <code>AA1BB2</code> would be a four-dimensional coordinate <code>(AA,1,BB,2)</code>.</p> <p>Because each component is independent, to expand the range between two coordinates we just return all combinations of the expansion of each component. Below is a quick implementation I cooked up this afternoon. It works for an arbitrary number of alternations of normal and alphabetic numbers, and handles large alphabetic ranges (i.e. from <code>AB</code> to <code>CDE</code>, not just <code>AB</code> to <code>CD</code>).</p> <p><strong>Note:</strong> This is intended as a rough draft of an actual implementation (I'm taking off tomorrow, so it is even less polished than usual ;). All the usual caveats regarding error handling, robustness, (readability ;), etc, apply.</p> <pre><code>IEnumerable&lt;string&gt; ExpandRange( string start, string end ) { // Split coordinates into component parts. string[] startParts = GetRangeParts( start ); string[] endParts = GetRangeParts( end ); // Expand range between parts // (i.e. 1-&gt;3 becomes 1,2,3; A-&gt;C becomes A,B,C). int length = startParts.Length; int[] lengths = new int[length]; string[][] expandedParts = new string[length][]; for( int i = 0; i &lt; length; ++i ) { expandedParts[i] = ExpandRangeParts( startParts[i], endParts[i] ); lengths[i] = expandedParts[i].Length; } // Return all combinations of expanded parts. int[] indexes = new int[length]; do { var sb = new StringBuilder( ); for( int i = 0; i &lt; length; ++i ) { int partIndex = indexes[i]; sb.Append( expandedParts[i][partIndex] ); } yield return sb.ToString( ); } while( IncrementIndexes( indexes, lengths ) ); } readonly Regex RangeRegex = new Regex( "([0-9]*)([A-Z]*)" ); string[] GetRangeParts( string range ) { // Match all alternating digit-letter components of coordinate. var matches = RangeRegex.Matches( range ); var parts = from match in matches.Cast&lt;Match&gt;( ) from matchGroup in match.Groups.Cast&lt;Group&gt;( ).Skip( 1 ) let value = matchGroup.Value where value.Length &gt; 0 select value; return parts.ToArray( ); } string[] ExpandRangeParts( string startPart, string endPart ) { int start, end; Func&lt;int, string&gt; toString; bool isNumeric = char.IsDigit( startPart, 0 ); if( isNumeric ) { // Parse regular integers directly. start = int.Parse( startPart ); end = int.Parse( endPart ); toString = ( i ) =&gt; i.ToString( ); } else { // Convert alphabetic numbers to integers for expansion, // then convert back for display. start = AlphaNumberToInt( startPart ); end = AlphaNumberToInt( endPart ); toString = IntToAlphaNumber; } int count = end - start + 1; return Enumerable.Range( start, count ) .Select( toString ) .Where( s =&gt; s.Length &gt; 0 ) .ToArray( ); } bool IncrementIndexes( int[] indexes, int[] lengths ) { // Increment indexes from right to left (i.e. Arabic numeral order). bool carry = true; for( int i = lengths.Length; carry &amp;&amp; i &gt; 0; --i ) { int index = i - 1; int incrementedValue = (indexes[index] + 1) % lengths[index]; indexes[index] = incrementedValue; carry = (incrementedValue == 0); } return !carry; } // Alphabetic numbers are 1-based (i.e. A = 1, AA = 11, etc, mod base-26). const char AlphaDigitZero = (char)('A' - 1); const int AlphaNumberBase = 'Z' - AlphaDigitZero + 1; int AlphaNumberToInt( string number ) { int sum = 0; int place = 1; foreach( char c in number.Cast&lt;char&gt;( ).Reverse( ) ) { int digit = c - AlphaDigitZero; sum += digit * place; place *= AlphaNumberBase; } return sum; } string IntToAlphaNumber( int number ) { List&lt;char&gt; digits = new List&lt;char&gt;( ); while( number &gt; 0 ) { int digit = number % AlphaNumberBase; if( digit == 0 ) // Compensate for 1-based alphabetic numbers. return ""; char c = (char)(AlphaDigitZero + digit); digits.Add( c ); number /= AlphaNumberBase; } digits.Reverse( ); return new string( digits.ToArray( ) ); } </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload