Manipulating lists differences

I noticed a difference in behavior when adding items to a list depending on how you write it. This is not the entire script, but just an example I made for you.

set answer to "B"
set possibleAnswers to {"A", "B", "C", "D"}
if answer is "A" then
	set possibleAnswers to items 2 thru -1 of possibleAnswers
else if answer is "B" then
	set possibleAnswers to item 1 of possibleAnswers & items 3 thru 4 of possibleAnswers
end if

possibleAnswers

result = “ACD”

If you make it say set possible answers to items 1 thru 1:

set answer to "B"
set possibleAnswers to {"A", "B", "C", "D"}
if answer is "A" then
	set possibleAnswers to items 2 thru -1 of possibleAnswers
else if answer is "B" then
	set possibleAnswers to items 1 thru 1 of possibleAnswers & items 3 thru 4 of possibleAnswers
end if

possibleAnswers

results = {“A”, “C”, “D”}

Just thought I would share what I found.

D

That is expected behavior.
When using ampersands, it all depends on what the first item is.
If the first item returns a string, then AppleScript will try to concatenate the rest of the items coerced to strings.
If the first item returns a list or number, then AppleScript will coerce to lists.

1 Like

or

set possibleAnswers to {item 1 of possibleAnswers} & items 3 thru 4 of possibleAnswers

1 Like

I appreciate the answers! I was sure there was a more elegant way, but I couldn’t discern what that would be. Thanks!

General solution:

on removeValue:aValue fromList:aList
	tell aList to if aValue is in it then
		repeat with k from 1 to count
			if (contents of item k) = aValue then exit repeat
		end repeat
		if k = 1 then return rest
		if k = (count) then return items 1 thru -2
		return items 1 thru (k - 1) & items (k + 1) thru -1
	end if
	return aList
end removeValue:fromList:

my removeValue:"B" fromList:{"A", "B", "C", "D"}
1 Like

This is useful — it is straightforward and a model of brevity.

To make it remove all instances of an item from a list, I added a repeat loop. To avoid some repetition, I commented out two of the if statements (anticipating that the first and last items will not match).

on removeValue:aValue fromList:aList
	tell aList to if aValue is in it then
		repeat with k from 1 to count
			if (contents of item k) = aValue then exit repeat
		end repeat
		-- if k = 1 then return rest
		-- if k = (count) then return items 1 thru -2
		return items 1 thru (k - 1) & items (k + 1) thru -1
	end if
	return aList
end removeValue:fromList:

set rawt to (path to desktop) & "ugly.txt" as text as alias
set wordList to words of (read rawt)
set badWord to "then"

with timeout of 4 seconds
	repeat while wordList contains badWord
		set wordList to my removeValue:badWord fromList:wordList
	end repeat
	-- display dialog length of wordList as text giving up after 3 -- test for completion
	return wordList
end timeout

The text document used is just a copy/paste of all the words on this page (excluding my own post) — it amounts to 767 words and includes twelve instances of ‘then’.

Or in JavaScript

function removeValue(value, list) {
   /* Build a new array containing only 
      those items not matching "value" */
   return list.filter(item => item !== value); 
}
const words = "I will not go home";
/* "split" builds an array from the words in "words" */
console.log(removeValue("not", words.split(' ')));

Output: I,will,go,home

No. I don’t have code where speed is important. And bun.sh (as node.js) doesn’t really offer OSA integration (yes, I know, there are node.js modules. Kind of).