Make a list of lists from a list

I’m working with this dataset:


set centerdata to {"CELTA Online Intensive 4-6 wks", "Mexico City, Mexico", "November 2 -  December 11 2020", "December 21 2020 - January 29 2021", "$1250 USD", "CELTA Online Intensive 4-6 wks", "Buenos Aires, Argentina", "September 14 - October 16 2020", "$1470 USD", "CELTA Online Intensive 4-6 wks", "Austin, USA", "September 7 – October 2 2020", "October 26 - November 20 2020", "$1995 USD", "CELTA Online Intensive 4-6 wks", "Springfield, Missouri, USA", "September 14 - October 16 2020 ", "October 19 - November 20 2020 ", "$2200 USD*", "CELTA Online Intensive 4-6 wks", "Vancouver (West Pender Street) Canada", "September 14 - October 23 2020", "November 02 - December 11 2020", "$2495 CAD", "CELTA Online Intensive 4-6 wks", "Toronto (Jarvis Street), Canada", "August 24 - September 18 2020 ", "$2000 USD", "CELTA Online Intensive 4-6 wks", "Toronto (Eglinton Avenue), Canada", "September 14 – October 16 2020", "October 26 – November 27 2020", "$2695 CAD", "CELTA Online Intensive 4-6 wks", "Los Angeles, (Koreatown) California, USA", "August 24 - September 18 2020", "September 21 - October 16 2020", "$2595 USD", "CELTA Online Intensive 4-6 wks", "New York City (West 26th Street), USA", "August 24 - September 18 2020", "November 16 - December 11 2020", "November 16 - December 11 2020", "$2595 USD", "CELTA Online Intensive 4-6 wks", "Portland, Oregon, USA", "August 24 - September 18 2020", "September 21 - October 16 2020", "$2595 USD", "CELTA Online P/T 7+ wks", "Mexico City, Mexico", "August 24 -  November 13 2020*", "September 7 - November 27 2020**", "September 21 -  December 11 2020**", "October 5 -  December 18 2020**", "October 19 -  December 31 2020**", "November 9 2020 - February 5 2021**", "November 23 2020 - February 19  2021**", "December 7 2020 - March 5 2021**", "*$1250 USD / **$1400 USD ", "CELTA Online P/T 7+ wks", "Springfield, Missouri, USA", "September 21 - December 4 2020 ", "December 28 2020 - March 12 2021 ", "$2200 USD*", "CELTA Online P/T 7+ wks", "Montreal, Canada", "August 24 - November 13 2020", "October 5 - December 24 2020", "November 23 2020 - February 2 2021", "$2400 CAD", "CELTA Online P/T 7+ wks", "Toronto (Eglinton Avenue), Canada", "September 8 – November 28 2020", "$2695 CAD", "CELTA Online P/T 7+ wks", "Vancouver (West Pender Street) Canada", "September 8 - November 27 2020", "$2495 CAD"}

I’m trying to make a new list from this list or convert this list to a list of lists. Each list in the new list of lists should have the “CELTA Online” as the first item.

Or to put it another way, if I were to put this into a spreadsheet, each row should start with the item that contains “CELTA Online”, followed by the other items until the next ‘CELTA Online’ is encountered, in which case, it would go into the next row.

I’m trying to make it look like:

{
{“CELTA Online Intensive 4-6 wks”, “Mexico City, Mexico”, “November 2 - December 11 2020”, “December 21 2020 - January 29 2021”, “$1250 USD”},
{“CELTA Online Intensive 4-6 wks”, “Buenos Aires, Argentina”, “September 14 - October 16 2020”, “$1470 USD”}
}

Each row has a variable number of items, which has made this a bit difficult for me to figure out. Any ideas?

My suggestion. The reference-to operator will make the script faster if the centerData list is significantly increased in size. Otherwise, it has no real impact one way or the other.


set centerData to {"CELTA Online Intensive 4-6 wks", "Mexico City, Mexico", "November 2 - December 11 2020", "December 21 2020 - January 29 2021", "$1250 USD", "CELTA Online Intensive 4-6 wks", "Buenos Aires, Argentina", "September 14 - October 16 2020", "$1470 USD", "CELTA Online Intensive 4-6 wks", "Austin, USA", "September 7 – October 2 2020", "October 26 - November 20 2020", "$1995 USD", "CELTA Online Intensive 4-6 wks", "Springfield, Missouri, USA", "September 14 - October 16 2020 ", "October 19 - November 20 2020 ", "$2200 USD*", "CELTA Online Intensive 4-6 wks", "Vancouver (West Pender Street) Canada", "September 14 - October 23 2020", "November 02 - December 11 2020", "$2495 CAD", "CELTA Online Intensive 4-6 wks", "Toronto (Jarvis Street), Canada", "August 24 - September 18 2020 ", "$2000 USD", "CELTA Online Intensive 4-6 wks", "Toronto (Eglinton Avenue), Canada", "September 14 – October 16 2020", "October 26 – November 27 2020", "$2695 CAD", "CELTA Online Intensive 4-6 wks", "Los Angeles, (Koreatown) California, USA", "August 24 - September 18 2020", "September 21 - October 16 2020", "$2595 USD", "CELTA Online Intensive 4-6 wks", "New York City (West 26th Street), USA", "August 24 - September 18 2020", "November 16 - December 11 2020", "November 16 - December 11 2020", "$2595 USD", "CELTA Online Intensive 4-6 wks", "Portland, Oregon, USA", "August 24 - September 18 2020", "September 21 - October 16 2020", "$2595 USD", "CELTA Online P/T 7+ wks", "Mexico City, Mexico", "August 24 - November 13 2020*", "September 7 - November 27 2020**", "September 21 - December 11 2020**", "October 5 - December 18 2020**", "October 19 - December 31 2020**", "November 9 2020 - February 5 2021**", "November 23 2020 - February 19 2021**", "December 7 2020 - March 5 2021**", "*$1250 USD / **$1400 USD ", "CELTA Online P/T 7+ wks", "Springfield, Missouri, USA", "September 21 - December 4 2020 ", "December 28 2020 - March 12 2021 ", "$2200 USD*", "CELTA Online P/T 7+ wks", "Montreal, Canada", "August 24 - November 13 2020", "October 5 - December 24 2020", "November 23 2020 - February 2 2021", "$2400 CAD", "CELTA Online P/T 7+ wks", "Toronto (Eglinton Avenue), Canada", "September 8 – November 28 2020", "$2695 CAD", "CELTA Online P/T 7+ wks", "Vancouver (West Pender Street) Canada", "September 8 - November 27 2020", "$2495 CAD"}


set newCenterData to makeListOfLists(a reference to centerData)

on makeListOfLists(oldList)
	
	set newList to {}
	set tempList to {item 1 of oldList}
	repeat with i from 2 to (count oldList)
		set anItem to item i of oldList
		if anItem begins with "CELTA Online" then
			set end of newList to tempList
			set tempList to {anItem}
		else
			set end of tempList to anItem
		end if
	end repeat
	set end of newList to tempList
	
	return newList
	
end makeListOfLists

Two methods come to mind. Which one is best will depend on stuff. The first method is very similar to peavine’s:

script CELTA
	property info : {"CELTA Online ...", ... }
end script

tell (a reference to CELTA's info)
	repeat with x in it
		tell x to if it starts with "CELTA Online" then
			set [contents, L] to [it as list, it]
		else
			set [end of L, contents] to [contents, 0]
		end if
	end repeat
	set CSVdata to lists
end tell

CSVdata will contain your desired output. The list stored in CELTA’s info gets mutated, so if you want the original form of the data preserved, you might wish to duplicate the list first, or reconstruct it from the output later.

The second method utilises text item delimiters:

property NUL : character id 0
set centerData to {"CELTA ...", ...}

set text item delimiters to NUL
set centerData to centerData as text
set text item delimiters to {linefeed & "CELTA", "CELTA"}
set centerData to rest of paragraphs of (centerData's text items as text)
set text item delimiters to NUL

repeat with x in (a reference to my centerData)
	set x's contents to x's text items 1 thru -2
end repeat

return centerData

Annoyingly, can’t seem to eliminate the need for a repeat loop, at least if sticking to vanilla AppleScript.

Just to point out (yet again, CK) for the benefit of learners that AppleScript doesn’t have square brackets and they shouldn’t be used in code. They offer no advantage over braces here in any case. Otherwise the first script’s entertainingly devious. :slight_smile:

… as is the way multiple text item delimiters are used in the second script. It’s the first time I’ve seen them used like this. The text resulting from the initial coercion with delimiter character id 0 is known not to contain the first delimiter in {linefeed & “CELTA”, “CELTA”}, so it’s only the second which causes any splits. However, it’s the first that’s heeded when the resulting list’s coerced back to text. :cool:

How’s about:

set centerData to {"CELTA Online Intensive 4-6 wks", "Mexico City, Mexico", "November 2 - December 11 2020", "December 21 2020 - January 29 2021", "$1250 USD", "CELTA Online Intensive 4-6 wks", "Buenos Aires, Argentina", "September 14 - October 16 2020", "$1470 USD", "CELTA Online Intensive 4-6 wks", "Austin, USA", "September 7 – October 2 2020", "October 26 - November 20 2020", "$1995 USD", "CELTA Online Intensive 4-6 wks", "Springfield, Missouri, USA", "September 14 - October 16 2020 ", "October 19 - November 20 2020 ", "$2200 USD*", "CELTA Online Intensive 4-6 wks", "Vancouver (West Pender Street) Canada", "September 14 - October 23 2020", "November 02 - December 11 2020", "$2495 CAD", "CELTA Online Intensive 4-6 wks", "Toronto (Jarvis Street), Canada", "August 24 - September 18 2020 ", "$2000 USD", "CELTA Online Intensive 4-6 wks", "Toronto (Eglinton Avenue), Canada", "September 14 – October 16 2020", "October 26 – November 27 2020", "$2695 CAD", "CELTA Online Intensive 4-6 wks", "Los Angeles, (Koreatown) California, USA", "August 24 - September 18 2020", "September 21 - October 16 2020", "$2595 USD", "CELTA Online Intensive 4-6 wks", "New York City (West 26th Street), USA", "August 24 - September 18 2020", "November 16 - December 11 2020", "November 16 - December 11 2020", "$2595 USD", "CELTA Online Intensive 4-6 wks", "Portland, Oregon, USA", "August 24 - September 18 2020", "September 21 - October 16 2020", "$2595 USD", "CELTA Online P/T 7+ wks", "Mexico City, Mexico", "August 24 - November 13 2020*", "September 7 - November 27 2020**", "September 21 - December 11 2020**", "October 5 - December 18 2020**", "October 19 - December 31 2020**", "November 9 2020 - February 5 2021**", "November 23 2020 - February 19 2021**", "December 7 2020 - March 5 2021**", "*$1250 USD / **$1400 USD ", "CELTA Online P/T 7+ wks", "Springfield, Missouri, USA", "September 21 - December 4 2020 ", "December 28 2020 - March 12 2021 ", "$2200 USD*", "CELTA Online P/T 7+ wks", "Montreal, Canada", "August 24 - November 13 2020", "October 5 - December 24 2020", "November 23 2020 - February 2 2021", "$2400 CAD", "CELTA Online P/T 7+ wks", "Toronto (Eglinton Avenue), Canada", "September 8 – November 28 2020", "$2695 CAD", "CELTA Online P/T 7+ wks", "Vancouver (West Pender Street) Canada", "September 8 - November 27 2020", "$2495 CAD"}

set astid to text item delimiters
set text item delimiters to "\", \""
set centerData to "\"" & centerData & "\""
set text item delimiters to {"\"}, {\"CELTA", "\", \"CELTA"}
set centerData to (run script ("{{" & centerData's text items & "}}"))
set text item delimiters to astid

return centerData

:slight_smile:

As you noted, though, these methods depend on stuff: in this case, on the original strings not containing characters like “"”.

Thanks for the assistance, after running your suggestions, I realized that my data collection was flawed, I have since normalized it so that each row does not have a variable number of fields or columns. I created an extra record for each unique date range that existed.