Creating a new list from another list

I’m fairly new to Applescript and am having a hard time getting my head around some of the syntax. I’ve done a good bit of Javascript and in those terms I’m trying to create a new array out of certain elements of another array. Below is my code that’s giving me an error. The code is being used in an Automator workflow. What I’m trying to do is loop through the input array and create a new array out of all the items with a certain label color. THe part that is giving me trouble is the line where I try to add the item to the new list “output”.

on run {input, parameters}
	set i to 1
	set output to {}
	repeat with curItem in input
		tell application "Finder"
			if label index of item curItem is equal to 2 then
				display alert "skipping this item"
			else
				set item i of output to curItem
				set label index of curItem to 2
			end if
		end tell
		i is equal to i + 1
	end repeat
	
	return output
end run

Hi,

try this:

on run {input, parameters}
    set output to {}
    repeat with curItem in input
        tell application "Finder"
            if label index of curItem is 2 then
                display alert "skipping this item"
            else
                set end of output to curItem
                set label index of curItem to 2
            end if
        end tell
    end repeat
    return output
end run

Note: the syntax to increment a variable is

set i to i + 1

Thanks StefanK your code seems to eliminate the errors. I’m having a new problem though. It’s hard to tell where it’s coming from though. The previous code should be returning a list of text files. After this Applescript section in the automator I combine the files and filter some paragraphs. Then another Applescript comes in and trys to subdivide the text up so that I can process the data. Below is the second section of AS code. I’m getting an error in the findAndReplace2 part. My suspicion is that the script does not have text to work with.

on run {input, parameters}
	set AppleScript's text item delimiters to {":"}
	--This is an example of what one of my text files should look like:: "Song File Names	01. Firehead.wav:Bass.wav:03. Steinslinger.wav:01. Firehead.wav:The Glenn Robinsons-That Bitch is a Trainwreck.mp3"
	
	set input to findAndReplace2("Song File Names	", "", input)
	set songList to every text item of input
	set outText to text item 1 of songList
	set AppleScript's text item delimiters to {""}
	set i to 1
	repeat until i > (count of songList)
		display alert "Item # " & i & " is " & text item i of songList
		set i to i + 1
	end repeat
	
	return songList
end run
on findAndReplace2(toFind, toReplace, theText)
	set astid to AppleScript's text item delimiters
	set AppleScript's text item delimiters to toFind
	set textItems to theText's text items
	set AppleScript's text item delimiters to toReplace
	--my error comes on the next line. Error -1728
        tell textItems to set editedText to beginning & toReplace & rest
	set AppleScript's text item delimiters to astid
	return editedText
end findAndReplace2

This line makes no sense: tell textItems to set editedText to beginning & toReplace & rest
you might try this instead…
set editedText to textItems as Unicode text

This should work because textItems is a list at this point, so you need to coerce the list to a string. When you convert it to a string it inserts whatever the astids are at that point between the items of the list… and just above this line you set the astids to the replace characters, so you should be good to go.

It’s a method invented by kai to return text of the same class as the original. If you use ‘as string’ or ‘as Unicode text’, you’re coercing the text items to something specific. The theory behind kai’s approach is that the text items will have the same class (string or Unicode text) as the text from which they’re derived. By starting with the first text item and using concatenation, the rules of concatenation will ensure that the rest of the line is coerced to the same class as the original text.

In byronnash’s second script, the findAndReplace2() handler is expecting its third parameter to be text, but it’s being passed ‘input’, which is probably a list. The same problem may occur with the line ‘set songList to every text item of input’. My guess is that a repeat loop’s needed to extract the individual item(s) from ‘input’.

Interesting! I didn’t know the word “rest”. :stuck_out_tongue: I see now that it returns items 2 thru end of the list.
His script seems too complicated for just returning a list of the song names. I think this is all he needs… besides a tutorial on text item delimiters… which he can see one by clicking here!

set input to "Song File Names    01. Firehead.wav:Bass.wav:03. Steinslinger.wav:01. Firehead.wav:The Glenn Robinsons-That Bitch is a Trainwreck.mp3"

set {TIDs, AppleScript's text item delimiters} to {AppleScript's text item delimiters, "Song File Names    "}
set song_files to text item 2 of input
set AppleScript's text item delimiters to ":"
set songList to text items of song_files
set AppleScript's text item delimiters to TIDs
return songList

Thanks for the help guys. I think my description and example code may have confused what I’m trying to do. The example string with the list of song names is just a sample of what my incoming text string may look like. I have several more steps before this in an automator workflow. This is my process basically:
Search for all text files named “OutputData”
Combine the contents into one text file.
Filter only the lines that begin with “Song FIle Names”
Use an applescript to remove the “Song FIle Names” from the text file and split the text list into an Applescript list. (this is the step shown in this thread)

After that I need to count how many times each song name is used by looping through the list. Then I just need to report all that to a simple text file.

Nigel may be right about what the scrip is sending, a list instead of a text item. I though I was sending text from input since the automator step before this AS is “Filter Paragraphs”

Ummm, did you look at my script above and did you do the tutorial in the link I posted?

If I’ve understood byron correctly and am right about the input to the Automator action, the value of ‘input’ will be a one-item list, something like {“Song File Names 01. Firehead.wav:Bass.wav:03. Steinslinger.wav:01. Firehead.wav:The Glenn Robinsons-That Bitch is a Trainwreck.mp3”}. The text will need to be extracted from the list, the first three words ditched, and the rest split into colon-delimited text items:

on run {input, parameters}
	set input to text from word 4 to -1 of (item 1 of input)
	
	set astid to AppleScript's text item delimiters
	set AppleScript's text item delimiters to ":"
	set songList to input's text items
	set AppleScript's text item delimiters to astid
	
	return songList
end run

This is very similar to regulus’s script, but in an Automator-action context.

If byron learns enough AppleScript, he could probably write the whole process as a single script, which should be more efficient than a series of Automator actions. :slight_smile:

I apologize for being all over the place here. I did a little testing and figured out that the snippet of code I put up here is working as it should. The problem is ANOTHER section of code that I’m using. The other code is supposed to only select items of a certain label color instead of the whole list. I thought it was working but apparently not. It’s not returning a proper list of items to the next automator step. You’re right Nigel about doing the whole thing in AS instead of messing with the Automator. I thought maybe I could save a little time using Automator this time until I get my head around AS. Here is my code for the other part, see if you can figure out what’s wrong. It’s supposed to take an input from a “Find Finder Items” node and feed it to a “Combine Text Files” node.

on run {input, parameters}
	set output to {}
	repeat with curItem in input
		tell application "Finder"
			if label index of curItem is 2 then
				--display alert "skipping this item"
			else
				set end of output to curItem
				set label index of curItem to 2
			end if
		end tell
	end repeat
	return output
end run

Hi, Byron.

Your code returns items that do not have a certain label index before the script’s run. In the process, it gives them that label.

on run {input, parameters}
	set output to {}
	repeat with curItem in input
		tell application "Finder"
			if label index of curItem is 2 then
				-- curItem's label index is 2. Ignore it.
			else
				-- curItem's label index is NOT 2.
				-- Append it to the output list.
				set end of output to curItem
				-- Set its label index to 2.
				set label index of curItem to 2
			end if
		end tell
	end repeat
	
	-- All the items that were in input now have color label 2.
	-- Only items that did not have that label to start with are in output.
	return output
end run

If you want instead to select items that already have label index 2:

on run {input, parameters}
	set output to {}
	repeat with curItem in input
		tell application "Finder"
			if label index of curItem is 2 then
				set end of output to curItem
			end if
		end tell
	end repeat
	
	return output
end run

Having been able to use my Tiger machine this morning, I have to say that when try the Automator sequence you describe, the scripts above output the relevant text file aliases, but for some reason, the “Combine Text Files” action only returns an empty string. Consequently, the “Filter Paragraphs” action (at which you hinted somewhere above) doesn’t pass any text at all and the next “Run AppleScript” tries to read text that isn’t there. (As you originally suspected.) That may be a big part of the problem: the “Combine Text Files” action itself seems to be duff. :confused:

I have more success if I combine the files during the first “Run AppleScript” script instead of using the “Combine Text Files” action:

on run {input, parameters}
	set output to ""
	repeat with curItem in input
		tell application "Finder"
			if label index of curItem is 2 then
				-- Concatenate the (string) text from this file to what we have already.
				set output to output & (read curItem)
			end if
		end tell
	end repeat
	
	return {output}
end run

The “Filter Paragraphs” action goes directly after that.

If more than one paragraph gets through the filter, the next “Run AppleScript” script (the one you were asking about yesterday) will need to cope with the fact that more than one line in the text begins with “Song File Names”. At the moment, it’s only geared up for one.

The script below combines all the stages from identifying which of the files returned by the first action have label index 2 to returning the song file names. It’s a lot faster than the four individual Automator actions it replaces. I don’t know if you want the names returned as a flat list or as a list of lists of names, each list of names corresponding to a “Song File Names” line. This script returns the latter. It’s easily changed if you want a flat list.

on run {input, parameters}
	set paragraphList to {}
	repeat with curItem in input
		tell application "Finder"
			if (label index of item curItem is 2) then
				-- If this text file's label index is 2,
				-- append its paragraphs to those already obtained.
				set paragraphList to paragraphList & paragraphs of (read curItem)
			end if
		end tell
	end repeat
	
	-- (A script object for speed in dealing with the paragraph list.)
	script o
		property p : paragraphList
	end script
	
	set astid to AppleScript's text item delimiters
	set AppleScript's text item delimiters to ":"
	
	-- Filter the paragraph list.
	repeat with i from 1 to (count paragraphList)
		set thisPara to item i of o's p
		if (thisPara begins with "Song File Names") then
			-- If this paragraph begins with "Song File Names",
			-- get its text from the fourth word on.
			set thisPara to text from word 4 to -1 of thisPara
			-- . and replace it in the list with a list of its colon-delimited text items.
			set item i of o's p to thisPara's text items
		else
			-- Otherwise replace the paragraph with a 'missing value'
			set item i of o's p to missing value
		end if
	end repeat
	
	set AppleScript's text item delimiters to astid
	
	-- Return the lists from the "paragraph" list.
	return paragraphList's lists
end run

Wow thanks Nigel your help has been invaluable. Sorry it’s taking me so long to reply to posts, I’m trying to juggle too many things at once right now. I have been working with your code and it seems to function properly. I do need all the list items for this part to be in one big list, not a list of lists(that’s for another part of the job). What I’ll be doing is returning a report of how many times a particular “Song Name” is used in the list. So after these steps I have been writing another loop to go through the list and compare the items to find matches.

What line changes the output to a big flat list? I tried changing the last line to

return paragraphList's items

but it did not work.

Hi, Byron.

If you’ll need both versions eventually (as I believe you’re saying), you can derive the flat list from the list of lists and return it too by replacing:

-- Return the lists from the "paragraph" list.
return paragraphList's lists

. with:

-- Get the lists from the "paragraph" list.
set listOfLists to paragraphList's lists

-- Concatenate them together to get a flat list of all their contents.
set songFileList to {}
repeat with i from 1 to (count listOfLists)
	set songFileList to songFileList & item i of listOfLists
end repeat

-- Return both the list of lists and the flat list.
return {listOfLists, songFileList}

Alternatively, if you don’t need the list of lists at all, you could simply build the flat list instead of it. The whole script would then be:

on run {input, parameters}
	set paragraphList to {}
	repeat with curItem in input
		tell application "Finder"
			if (label index of item curItem is 2) then
				-- If this text file's label index is 2,
				-- append its paragraphs to those already obtained.
				set paragraphList to paragraphList & paragraphs of (read curItem)
			end if
		end tell
	end repeat
	
	-- (A script object for speed in dealing with the paragraph list.)
	script o
		property p : paragraphList
	end script
	
	set astid to AppleScript's text item delimiters
	set AppleScript's text item delimiters to ":"
	
	-- Parse the song file names from the paragraph list.
	set songFileNames to {}
	repeat with i from 1 to (count paragraphList)
		set thisPara to item i of o's p
		if (thisPara begins with "Song File Names") then
			-- If this paragraph begins with "Song File Names",
			-- get its text from the fourth word on.
			set thisPara to text from word 4 to -1 of thisPara
			-- . and concatenate the colon-delimited text items of the result to the list of song file names.
			set songFileNames to songFileNames & thisPara's text items
		end if
	end repeat
	
	set AppleScript's text item delimiters to astid
	
	-- Return the list of song file names.
	return songFileNames
end run

Thanks Nigel, I’m finally starting to make some decent progress out of this thing. It is pretty stupid that I’m using the automator. I should have just done it with AS from the start. I’m sure there will be plenty more snafu’s for me here so I’ll be asking more questions.