Looping

What I want to do is group 5 items and then have a return after those. Basically I want a group of 5, then a return. I don’t know the total number of items (totalNum) and that’s why I can’t use repeat or some other easier way of doing this.

Can you guys help me figure out what’s wrong or a better way of doing it?

set totalNum to 25
set itemCount to 1
set desktopPath to path to desktop as string
set fileID to open for access desktopPath & "testloop2.txt" with write permission
write "" to fileID starting at eof
repeat with i from 1 to totalNum
	if itemCount is not equal to 5 then
		set writeCode to i as string
		write writeCode & ", " to fileID
		set i to i + 1
		set itemCount to itemCount + 1
	else
		write return to fileID
		set i to i - 1
		set itemCount to 1
		
	end if
end repeat
close access fileID

Gives me this result:

It skips numbers, I can’t have that happen.

You need help with sorting out what you have. Study this little script:

set Total to (text returned of (display dialog "Enter a number" default answer "22")) as number

set Fives to Total div 5
set Extra to Total mod 5

(Fives as text) & " Fives, with " & Extra & " left over"

--> for 22 gives "4 Fives, with 2 left over"

The first line let you try any number you like, the second and third get you how many rows of five there will be and then one row of the Extra.

Don’t write every time as you go along - assemble a big string (with your returns) and then write the whole thing in one swoop. Otherwise you’ll spend all your time waiting for the disk.

I came up with this subroutine:

set testList to {"1", "2", "3", "4", "5", "6", "7", "8", "9"}

makeCommaSeperatedLines(testList, 5, ", ")

on makeSeperatedLines(someList, groupAmount, aSeparator)
	set numGroups to round ((count someList) / groupAmount) rounding up
	set remainder to groupAmount - ((count someList) mod groupAmount)
	
	set newText to {}
	set ASTID to AppleScript's text item delimiters
	set AppleScript's text item delimiters to aSeparator
	
	repeat with i from 1 to numGroups
		if (i is not equal to numGroups) then
			get groupAmount * i
			get {result - groupAmount + 1, result}
		else
			get groupAmount * i
			get {result - groupAmount + 1, result - remainder}
		end if
		
		set newText's end to ((items (get first item of result) thru (get second item of result)) of someList) as Unicode text
	end repeat
	
	set AppleScript's text item delimiters to {ASCII character 13}
	set newText to newText as Unicode text
	set AppleScript's text item delimiters to ASTID
	return newText
end makeSeperatedLines

Hi.

The original query’s a little ambiguous. Does it mean rows of any “items” or rows of numbers starting from 1? Is the text file a way of achieving this or is it an end in itself?

The reason the original script gives the results it does is that, in the ‘else’ section of the ‘if’ block, only the return is being written to the file. It should be the number as string (and a comma?) and the return.

A consequence of Adam’s point about using ‘mod’ is that if (someNumber mod 5) is 0, then that number is exactly divisible by 5. We can thus check for the loop counter’s divisibility by 5 rather than having to maintain a separate counter that gets reset to 1 every time it reaches 5. This is both more economical and (to my mind) easier to get right.

set totalNum to 25
set numbersPerLine to 5

set separator to ", "
set lineEnd to "," & return

set collector to {}

repeat with i from 1 to totalNum
	set end of collector to i
	if (i is totalNum) then
		-- Insert a final return?
	else if (i mod numbersPerLine is 0) then
		set end of collector to lineEnd
	else
		set end of collector to separator
	end if
end repeat

set astid to AppleScript's text item delimiters
set AppleScript's text item delimiters to ""
set outputStr to collector as string
set AppleScript's text item delimiters to astid

return outputStr -- or write it to file.

(* Result:
"1, 2, 3, 4, 5,
6, 7, 8, 9, 10,
11, 12, 13, 14, 15,
16, 17, 18, 19, 20,
21, 22, 23, 24, 25" *)

I have an applescript list of data that I want to write to a text file. I want that data to be in groups of five seperated only by a return.


set writeData to {'item1','item2','item3','item4','item5','item6','item7'}  --I don't know how long the list will be. 

and I want the text file to be:

Thanks for your help

Details are important. A normal AppleScript list wouldn’t compile with the single quotes you show, and it would have a space after every comma. You want the groups separated by a return character but you want the items separated by spaces? Give us a real example of what writeData might look like (something that passed muster in the Script Editor), and put in a few lines of what the output text for that list should look like.

In the meantime, something like this (using Nigel Garvey’s script) works for me:

set dataList to {"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"}

set totalNum to count of dataList
set numbersPerLine to 5
set separator to space
set lineEnd to return
set collector to {}

repeat with k from 1 to totalNum
	set end of collector to item k of dataList
	if (k is totalNum) then
		writeData(collector)
	else if (k mod numbersPerLine is 0) then
		set end of collector to lineEnd
	else
		set end of collector to separator
	end if
end repeat

on writeData(theList)
	set astid to AppleScript's text item delimiters
	set AppleScript's text item delimiters to ""
	set outputStr to theList as string
	set AppleScript's text item delimiters to astid
	try
		set f to open for access (path to desktop as text) & "DataFile.txt" with write permission
		write outputStr to f
		close access f
	on error theError
		close access f
		display dialog theError
	end try
end writeData

Here is my attempt:

set theList to {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}
listToCommaDelimitedLines(theList, 5)

on listToCommaDelimitedLines(theList, rowWidth)
	repeat with i from 1 to ((count of theList) - 1) div rowWidth
		tell (a reference to item (i * rowWidth + 1) of theList) to ¬
			set contents to return & contents as Unicode text
	end repeat
	set text item delimiters to ", "
	set {theList, text item delimiters} to {text items of theList as Unicode text, ", " & return}
	set {theList, text item delimiters} to {text items of theList, "," & return}
	set {theList, text item delimiters} to {text items of theList as Unicode text, ""}
	theList
end listToCommaDelimitedLines

Thanks for all your responses. I got it to work using your suggestions and learned a bunch! One question though what does this do?

set astid to AppleScript's text item delimiters

Thanks!

AppleScript’s text item delimiters are a very powerful concept. A text item is any text between delimiters, so if I have this string: “Now is the time for all good men” and I set ASTID to “for” then the text items of the string are: “Now is the time” and “all good men”. By setting them to something else, I can replace “now” with the something else by reassembling the string: e.g.

set Str to "Now is the time for all good men"
set TID to text item delimiters -- store previous value [ALWAYS DO THIS OR YOU'LL BE SCREWED UP LATER - APPLESCRIPT REMEMBERS!]
set text item delimiters to "for"
set parts to text items of Str
--> {Now is the time, all good men}
-- now I can switch them and replace "now" with "with"
set text item delimiters to "with"
set NewString to parts as string -- as string puts the list back together as a single string with the delimiter chosen between
set text item delimiters to TID -- restore them.
--> "Now is the time with all good men"

I think you can see how powerful an idea this is when I want to find something and change it. In your script, Nigel Garvey suggested this step to be sure that if you were using a different TID, he’d fix it for his piece of the script and then set it back the way you had it.

Here’s another recent example: http://bbs.applescript.net/viewtopic.php?pid=51466, but there are lots here - use search on “text item delimiters”.