12 Replies Latest reply on Nov 13, 2008 10:16 PM by (charles_darwin)

    [JS][CS2]How to contract numbers

    Level 1
      Help script gurus.
      I found this wonderful script (thanks dave saunders) made by Peter Kahrel. Wow thanks to you it helps a lot.

      unranged_array = unrange ("1,5,6-11")

      function unrange (s)
      {
      return s.replace (/(\d+)-(\d+)/g, expand)
      }

      function expand ()
      {
      var expanded = [];
      var start = Number (arguments[1]);
      var stop = Number (arguments[2]);
      for (var i = start; i <= stop; i++)
      expanded.push (i);
      return expanded
      }

      The script returns "1,5,6,7,8,9,10,11". What if i change some of the numbers in the array let's say i want it this way: "1,5,6,12,13,9,10,11".

      Is there anyway we can arrange it to ascending order ("1,5,6,9,10,11,12,13")?
      Then contract ("1,5,6,9-13")?

      Please help gurus.
        • 1. Re: [JS][CS2]How to contract numbers
          (Simon_Paterson) Level 1
          Would that actually be "1,5-6,9-13" or are you deliberately not contracting numbers that are only 1 apart?
          • 2. Re: [JS][CS2]How to contract numbers
            (Simon_Paterson) Level 1
            I'm trying something out at the moment for you.
            • 3. Re: [JS][CS2]How to contract numbers
              Level 1
              there's nothing in between 5-6 so i just leave it.
              Thank you very much Simon.
              • 4. Re: [JS][CS2]How to contract numbers
                (Simon_Paterson) Level 1
                Oh, okay, nothing between 5 and 6. Cool.
                • 5. Re: [JS][CS2]How to contract numbers
                  (Simon_Paterson) Level 1
                  The following is a little inelegant, but it gets the job done. Hopefully someone will point out a better way to skin this cat.

                  I've made this a function and put in an option to skip sequential numbers, just in case anybody else wants to use this for index-style entries where they wouldn't normally skip sequential numbers.

                  myArray should be a list of numbers sorted in ascending order.

                  Note that the final result, however, is an array of strings.

                  Just call something like: myContractedArray = ContractArray(myArray,true);

                  >function ContractArray(myArray,mySkipSequenceOption)
                  {
                  ]var myRefined = new Array;
                  var mySpanning = new Array;
                  var myStartPoint = myArray[0];
                  for (var a = 1; a < myArray.length; a++) {
                  ]]if (myArray[a] != myStartPoint + 1) {
                  ]]]if (mySpanning.length != 0) {
                  ]]]]myRefined.push(mySpanning);

                  mySpanning = new Array;
                  ]]]]}
                  ]]]else {
                  ]]]]myRefined.push(myStartPoint);
                  ]]]]}
                  ]]]}
                  ]]else {
                  ]]]if (mySpanning.length == 0) {
                  ]]]]mySpanning.push(myStartPoint);
                  ]]]]}
                  ]]]mySpanning.push(myArray[a]);
                  ]]]}
                  ]]if (a == myArray.length - 1) {
                  ]]]if (mySpanning.length != 0) {
                  ]]]]myRefined.push(mySpanning);
                  ]]]]}
                  ]]]else {
                  ]]]]myRefined.push(myArray[a]);
                  ]]]]}
                  ]]]}
                  ]]else {
                  ]]]myStartPoint = myArray[a];
                  ]]]}
                  ]]}
                  ]var myFinal = new Array;
                  ]for (var b = 0; b < myRefined.length; b++) {
                  ]]if (myRefined[b].constructor.name != "Array") {
                  ]]]myFinal.push(myRefined[b].toString());
                  ]]]}
                  ]]else {
                  ]]]if (mySkipSequenceOption == true && myRefined[b].length == 2) {
                  ]]]]myFinal.push(myRefined[b][0].toString());

                  myFinal.push(myRefined[b][1].toString());
                  ]]]]}
                  ]]]else {
                  ]]]]myFinal.push(myRefined[b][0] + "-" + myRefined[b][myRefined[b].length - 1]);
                  ]]]]}
                  ]]]}
                  ]]}
                  ]return myFinal;

                  }

                  I'll have a longer think about this and come up with a better method if nobody has done so already. Something just seems so wrong about the way I'm doing this but my head is foggy at the moment so I'll come back to this later.
                  • 6. Re: [JS][CS2]How to contract numbers
                    Peter Kahrel Adobe Community Professional & MVP
                    Here's (a variation) of a script I use to unrange, sort, and rerange a sequence of numbers.

                    Peter


                    s = "1,5,6,12,13,9-11";
                    unranged = unrange (s);
                    unranged_sorted = unranged.split(',').sort (sortnum);
                    reranged = range (unranged_sorted);

                    function unrange (s)
                       {
                       return s.replace (/(\d+)-(\d+)/g, expand)
                       }

                    function expand ()
                       {
                       var expanded = [];
                       var start = Number (arguments[1]);
                       var stop = Number (arguments[2]);
                       for (var i = start; i <= stop; i++)
                          expanded.push (i);
                       return expanded
                       }

                    function sortnum (a, b)
                       {
                       return a - b
                       }

                    function range (array)
                       {
                       var temp = [];
                       var i = 0;
                       while (i < array.length)
                          {
                          if ((array[i+1] - array[i] == 1) && (i < array.length))
                             {
                             var subrange = array[i] + '\u2013';
                             while ((array[i+1] - array[i] == 1) && (i < array.length))
                                i++;
                             temp.push (subrange+array[i])
                             }
                          else
                             temp.push (array[i]);
                          i++
                          }
                       return temp.join (', ')
                       }
                    • 7. Re: [JS][CS2]How to contract numbers
                      (Simon_Paterson) Level 1
                      That is gorgeous, Peter. That is the elegance I aspire to achieve. Awesome.
                      • 8. Re: [JS][CS2]How to contract numbers
                        Level 1
                        you guys are amazing. i don't know what to say. wish i could write scripts like that someday. i'm a fan of yours peter i bought your ebook in o'reilly. thanks it helps me in so many ways.
                        • 9. Re: [JS][CS2]How to contract numbers
                          Level 1
                          the script returns:
                          1,56,913
                          can we ignore the 5-6?
                          can we make it:
                          1,5,6,9-13

                          thanks.
                          • 10. Re: [JS][CS2]How to contract numbers
                            (Simon_Paterson) Level 1
                            Charles, I'm working on a revised version of Peter's excellent function to help you with this. I'll post something soon, I hope. My version does what you need, but it is insanely inelegant. I shouldn't post when I'm tired.
                            • 11. Re: [JS][CS2]How to contract numbers
                              (Simon_Paterson) Level 1
                              The following seems to be working, but I haven't tested it extensively:

                              >function range (array)
                              {

                              var temp = [];

                              var i = 0;

                              while (i < array.length)

                              {

                              if ((array[i+1] - array[i] == 1 && array[i+2] - array[i+1] == 1) && (i < array.length))

                              {

                              var subrange = array[i] + '\u2013';

                              while ((array[i+1] - array[i] == 1) && (i < array.length))

                              i++;

                              temp.push (subrange+array[i])

                              }

                              else

                              temp.push (array[i]);

                              i++

                              }

                              return temp.join (', ')

                              }
                              • 12. Re: [JS][CS2]How to contract numbers
                                Level 1
                                I tested it. Works great! Thanks Simon for the effort I really appreciate your works guys.