Skip to main content
September 15, 2010
Question

chronological order number needs in index numbers to be changed as ndash

  • September 15, 2010
  • 2 replies
  • 12329 views
Hi all


I have a task to complete the below requirement for Index part in a book. Please help me.


I have sequence of numbers like this,


Index1, 26, 35, 36, 37, 47
Index2, 65, 78, 79, 89, 90


I need to change like this

Index1, 26, 35−37, 47
Index2, 65, 78−79, 89−90


i.e., the number which are in sequence order (chronological order) needs to be changed as ndash.

Sajeev

This topic has been closed for replies.

2 replies

Marc Autret
Legend
September 15, 2010

Hi all,

Here is the routine I use in IndexMatic 2 (script-in-progress). That's certainly equivalent to Bob's and/or Peter's approach, but why not sharing:

function makeSequences(/*Number[]*/numbers, /*String*/separator, /*String*/linker)
{
separator = separator || ", ";
linker = linker || "-";

if( numbers.length < 2 ) return numbers.join('');

var a = numbers.concat().sort(function(x,y){return x-y;}),
     sz = a.length-1, i = 0, i0 = 0, n = a[0], r = [];

var format = function()
     {
     r.push(a[i0] + ((i-i0)>1 ? linker+a[i-1] : ''));
     return i0=i;
     };

while( i<sz && ( n+1>=(n=a[++i]) || format()));
format();
return r.join(separator);
}


// Sample code:

var myTest1 = [ 1, 2, 4, 6, 9, 10, 11, 12, 13, 14, 15, 18, 19, 30 ];
alert( makeSequences(myTest1, ", ", "\u2013") );
// => 1–2, 4, 6, 9–15, 18–19, 30

var myTest2 = [ 5, 3, 4, 4, 6, 6, 9, 12, 1, 18, 21, 22, 22, 0, 8 ];
alert( makeSequences(myTest2, " | " ) );
// => 0-1 | 3-6 | 8-9 | 12 | 18 | 21-22

@+

Marc

Harbs.
Legend
September 15, 2010

Since we're all sharing, here's the function I wrote about two and a half years ago. (If I were writing it now, it would probably look a lot nicer...)


function FixIndexRanges(){
    var story = app.selection[0].parentStory;
    var storyWords = story.words;
    for(var i=storyWords.length-1;i>0;i--){
        var curNumber = parseFloat(storyWords.contents);
        var prevNumber = parseFloat(storyWords[i-1].contents);
        if(curNumber!=NaN && prevNumber!=NaN && prevNumber==curNumber-1){
            var insertNumber = curNumber+0;
            var theIndex = storyWords.characters[0].index-1;
            while(prevNumber==insertNumber-1){
                i--;
                insertNumber--;
                try{
                    var prevNumber = parseFloat(storyWords[i-1].contents);
                    }catch(e){break}
                }
            var theIPIndex = storyWords.insertionPoints[0].index;
            story.texts.itemByRange(storyWords.characters[0],story.characters.item(theIndex)).remove();
            story.insertionPoints[theIPIndex].contents=insertNumber+'-';
            }
        }
    }

Harbs

September 16, 2010

cool script  Harbs

really nice one

Sajeev

Bob Stucky
Adobe Employee
Adobe Employee
September 15, 2010

Thanks for the fun morning algorithm exercise...

I think this will do it for you.

Regards

Bob

indexize = function( ar ) {
    var out = new Array();
    for ( var i = 0; i < ar.length; i++ ) {
        var a = i + 1;
        var current = ar[ i ];
        var concat = false;
        while ( parseInt( ar[ a++ ] )== ( current + 1 ) ) {
            current = ar[ a - 1 ];
            concat = true;
        }
        if ( concat ) {
            if ( parseInt( ar[ i ] ) + 1 == current ) {
                out.push( ar[ i ] );
                out.push( ar[ i + 1 ] );
            } else {
                out.push( ar[ i ] + "-" + current  );
            }
        } else {
            out.push( ar[ i ] );
        }
        i = a - 2;
    }
    return out;
}

var a = [ 1, 2, 4, 5, 7, 9, 11, 12, 15, 16, 17, 18, 19, 20, 22, 23, 25, 26, 27, 30, 31, 33, 34, 35, 36, 40, 41, 43,44,45,47,48,50 ];
$.writeln( "Input: " + a );
debugger;
$.writeln( "Output: " + indexize( a ) );

Bob Stucky
Adobe Employee
Adobe Employee
September 15, 2010

Oh, and do you really want 65,78,89,90 to contain 89-90?

It doesn't make sense (to me) to have sequences of 2 digits have a hyphen.

But if you do, make the "if (concat)" block look something like:

out.push( concat ? ( ar[ i ] + "-" + current ) : ar[ i ] );

Bob

Community Expert
June 30, 2011

Hi Laubender,

I don't get that issue whith the version of formatRanges that I've posted above (#17).

The function supports "empty array, unsorted array, duplicated elems, negative values."

//TESTS:
var a = [1,1,10,10,11,11,11,11,11,14,15,16,222,222,223,289];

alert("Tolerance: 0\t" + formatRanges(a, ', ', '-', 1, 0));
// Returns: 1, 10-11, 14-16, 222-223, 289

alert("Tolerance: 1\t" + formatRanges(a, ', ', '-', 1, 1));
// Returns: 1, 10-11, 14-16, 222-223, 289

alert("Tolerance: 2\t" + formatRanges(a, ', ', '-', 1, 2));
// Returns: 1, 10-16, 222-223, 289


function formatRanges(numbers, separator, joiner, minWidth, tolerance)
//----------------------------------------------------------
// Formats an array of integers into an ordered sequence of
// single numbers and/or ranges. Returns the formatted string.
//
// <numbers>     Array of Numbers [required]
//                    The integers to format. Supports: empty array,
//                    unsorted array, duplicated elems, negative values.
//
// <separator>     String [opt] -- Default value: ", ".
//                    A string inserted between each result.
//                    Ex.     formatRanges([4,1,3,8,9,6], " | ")
//                         => "1 | 3-4 | 6 | 8-9"
//
// <joiner>          String [opt] -- Default value: "-".
//                    A string used to format a range.
//                    Ex.     formatRanges([4,1,3,8,9,6], ", ", "_")
//                         => "1, 3_4, 6, 8_9"
//
// <minWidth>     Number [opt] -- Default value: 1.
//                    Minimum distance between the 1st and the last
//                    number in a range.
//                    Ex.     formatRanges([1,2,4,5,6,8,9,10,11], '', '', 1)
//                         => "1-2, 4-6, 8-11"
//                    Ex.     formatRanges([1,2,4,5,6,8,9,10,11], '', '', 2)
//                         => "1, 2, 4-6, 8-11"
//                    Ex.     formatRanges([1,2,4,5,6,8,9,10,11], '', '', 3)
//                         => "1, 2, 4, 5, 6, 8-11"
//
// <tolerance>     Number [opt] -- Default value: 0.
//                    Number of allowed missing numbers in a range,
//                    as suggested by Peter Kahrel (http://bit.ly/cABqIP)
//                    Ex.     formatRanges([2,3,5,8,12,17,23], '', '', 1, 0)
//                         => "2-3, 5, 8, 12, 17, 23"
//                    Ex.     formatRanges([2,3,5,8,12,17,23], '', '', 1, 1)
//                         => "2-5, 8, 12, 17, 23"
//                    Ex.     formatRanges([2,3,5,8,12,17,23], '', '', 1, 2)
//                         => "2-8, 12, 17, 23"
{
// Defaults
separator = separator || ", ";
joiner = joiner || "-";
if( minWidth !== ~~minWidth || minWidth < 1 ) minWidth = 1;
if( tolerance !== ~~tolerance || ++tolerance < 1 ) tolerance = 1;

// Init.
var a = numbers.concat().sort(function(x,y){return x-y;}),
     sz = a.length,
     n = sz && a[0],
     d = sz || false,
     i = 0, w = 0, t = 0,
     ret = [];

// Loop
while( d !== false )
     {
     if( 0 === (d=(++i<sz)?a-n:false) )
          continue;      // skip duplicates

     if( d && (d<=tolerance) )
          {
          ret.push(n);
          n += d;
          ++w;
          t += (d-1);
          continue;
          }
     
     if( w >= minWidth )
          {
          ret.length -= w;
          ret.push((n-w-t)+joiner+n);
          }
     else
          {
          ret.push(n);
          }
     n += d;
     w = t = 0;
     }

return ret.join(separator);
}

@+

Marc


@Marc,

yes, I saw that as I tested your function as well. Thank you for your effort …
It's tough for me to exactly understand what's going on in your function elegant as it is.

Uwe