Consolidate Individual Pages and Page Ranges

I’m looking for a way to consolidate page-number input, so that sequential individual pages are made into page ranges or added to existing page ranges. For example:

-- AppleScript Input (a string)
"1 2 3 4 6-8 10 12 13 14 17 18-20"

-- Desired AppleScript Output (a string)
"1-4 6-8 10 12-14 17-20"

With significant help from Google AI, I wrote a solution. As presented, it’s poorly written, but I stopped without further work (which includes understanding the Google AI code), because I had to wonder if there’s an entirely different approach that might be simpler. If not, I’ll clean-up the existing script and use that. The script only took a millisecond to run, so speed is not an issue.

Thanks for any suggestions.

set oldPageString to "1 2 3 4 6-8 10 12 13 14 17 18-20 21-22"
set text item delimiters to space
set oldPageList to text items of oldPageString

--Make page ranges into individual page numbers
set tempPageList to {}
repeat with aPageItem in oldPageList
	if aPageItem does not contain "-" then
		set end of tempPageList to aPageItem as integer
	else
		set text item delimiters to "-"
		set tempRangeList to {}
		repeat with i from (text item 1 of aPageItem) to (text item 2 of aPageItem)
			set end of tempPageList to i
		end repeat
	end if
end repeat

--Most of the following is from Google AI
set rangeList to {}
set currentRangeStart to item 1 of tempPageList
set currentRangeEnd to item 1 of tempPageList

repeat with i from 2 to count of tempPageList
	set currentNum to item i of tempPageList
	set previousNum to item (i - 1) of tempPageList
	--Check if the current number is sequential to the previous
	if currentNum is equal to (previousNum + 1) then
		set currentRangeEnd to currentNum
	else
		-- If not sequential, finalize the previous range and start a new one
		addToRangeList(rangeList, currentRangeStart, currentRangeEnd)
		set currentRangeStart to currentNum
		set currentRangeEnd to currentNum
	end if
end repeat

--Add the last range after the loop finishes
addToRangeList(rangeList, currentRangeStart, currentRangeEnd)

set text item delimiters to space
set newPageList to rangeList as text
set text item delimiters to ""
return newPageList

on addToRangeList(rangeList, startNum, endNum)
	if startNum is equal to endNum then
		copy (startNum as string) to the end of rangeList
	else
		copy (startNum as string) & "-" & (endNum as string) to the end of rangeList
	end if
end addToRangeList

Hi peavine.

Here’s one possibility:

use AppleScript version "2.4" -- OS X 10.10 (Yosemite) or later
use framework "Foundation"
use scripting additions

set oldPages to "1 2 3 4 6-8 10 12 13 14 17 18-20 21-22"

set indexSet to current application's class "NSMutableIndexSet"'s indexSet()
repeat with thisEntry in splitText(oldPages, space)
	if (thisEntry contains "-") then
		set {a, z} to splitText(thisEntry, "-")
		(indexSet's addIndexesInRange:({a as integer, z - a + 1}))
	else
		(indexSet's addIndex:(thisEntry as integer))
	end if
end repeat
set theDescription to indexSet's |description|()
set substringRange to theDescription's rangeOfString:("(?<=\\()[^\\)]++(?=\\)\\])") options:(current application's NSRegularExpressionSearch) range:({0, theDescription's |length|()})
set newPages to (theDescription's substringWithRange:(substringRange)) as text

on splitText(txt, delim)
	set astid to AppleScript's text item delimiters
	set AppleScript's text item delimiters to delim
	set output to txt's text items
	set AppleScript's text item delimiters to astid
	return output
end splitText
1 Like

Thanks Nigel. That works great and also takes about a millisecond to run. I’ll study that later today.

Or a simpler alternative:

set theDescription to indexSet's |description|() as text
set newPages to splitText(theDescription, {"(", ")]"})'s item -2