search for strings within a list

I have a list of over 5000 file names.

here’s a snippit.


set fileList to {"3579-08.jpg", "3579.jpg", "3580-08.jpg", "3580.jpg", "3581-08.jpg", "3581.jpg", "3582-08.jpg", "3582.jpg", "3583-04.jpg", "3583.jpg", "3584-04.jpg", "3586-06.jpg", "3588-08.jpg", "3588.jpg", "3590-08.jpg", "3590.jpg", "3591-04.jpg", "3591.jpg"}

What I really need is a way in which to search for a string like “3590” and return a new list that has both “3590-08.jpg” and “3590.jpg”

I was trying to do that with scriptDB, but I am getting an error on that. "Expression error: too many arguements "

set newList to {{"3579-08.jpg"}, {"3579.jpg"}, {"3580-08.jpg"}, {"3580.jpg"}, {"3581-08.jpg"}, {"3581.jpg"}, {"3582-08.jpg"}, {"3582.jpg"}, {"3583-04.jpg"}, {"3583.jpg"}, {"3584-04.jpg"}, {"3586-06.jpg"}, {"3588-08.jpg"}, {"3588.jpg"}, {"3590-08.jpg"}, {"3590.jpg"}, {"3591-04.jpg"}, {"3591.jpg"}}

set my_fields to {{"Image", string}}
set my_db to DB create with properties {DBName:"theImages", DBFields:my_fields}

set my_db to DB add records newList to db my_db

set my_data to DB get data from db my_db where {"Field(Image)", "=", "3591.jpg"}
--set my_data to DB get data from db my_db where {"Field(Image)", "contains", "3591"}

The error is generated regardless which of the last two commands I send it.

Anyone have any ideas for me?

Try this:


set fileList to {"3579-08.jpg", "3579.jpg", "3580-08.jpg", "3580.jpg", "3581-08.jpg", "3581.jpg", "3582-08.jpg", "3582.jpg", "3583-04.jpg", "3583.jpg", "3584-04.jpg", "3586-06.jpg", "3588-08.jpg", "3588.jpg", "3590-08.jpg", "3590.jpg", "3591-04.jpg", "3591.jpg"}
set foundList to {}
repeat with fileRecord in fileList
	if "3590" is in fileRecord then
		set foundList to foundList & fileRecord
	end if
end repeat
return foundList

That works great.

My only question would be whether there is a faster method. The repeat loop takes 6-7 seconds to navigate through all 5900 list items. And the script I am writing will be calling for that search over 2300 times.

In this case you might want to take a look at this tutorial: Introduction to SQLite3 - a Simple Database Engine
:wink:

Hi.

Martin’s script can be speeded up by referencing the list variables (making accessing the items faster), by appending items to the end of the target list instead of concatenating them to it (otherwise you’re creating two new lists each time), and by using ‘considering case’ (numbers don’t have any case to ignore).

set fileList to {"3579-08.jpg", "3579.jpg", "3580-08.jpg", "3580.jpg", "3581-08.jpg", "3581.jpg", "3582-08.jpg", "3582.jpg", "3583-04.jpg", "3583.jpg", "3584-04.jpg", "3586-06.jpg", "3588-08.jpg", "3588.jpg", "3590-08.jpg", "3590.jpg", "3591-04.jpg", "3591.jpg"}
set foundList to {}
considering case
	repeat with i from 1 to (count fileList)
		set fileRecord to item i of my fileList -- NB. 'my'.
		if "3590" is in fileRecord then
			set end of my foundList to fileRecord -- Ditto.
		end if
	end repeat
end considering
return foundList

In a handler, you’d need a script object to facilitate the references:

on myHandler(l, v)
	script o
		property fileList : l
		property foundList : {}
	end script
	
	considering case
		repeat with i from 1 to (count l)
			set fileRecord to item i of o's fileList
			if v is in fileRecord then
				set end of o's foundList to fileRecord
			end if
		end repeat
	end considering
	
	return o's foundList
end myHandler

set fileList to {"3579-08.jpg", "3579.jpg", "3580-08.jpg", "3580.jpg", "3581-08.jpg", "3581.jpg", "3582-08.jpg", "3582.jpg", "3583-04.jpg", "3583.jpg", "3584-04.jpg", "3586-06.jpg", "3588-08.jpg", "3588.jpg", "3590-08.jpg", "3590.jpg", "3591-04.jpg", "3591.jpg"}
set matchVal to "3590"

myHandler(fileList, matchVal)

Or you could coerce the list to a return-delimited text and use text item delimiters to pick out matching names. There should be far fewer text items to check than original items:

on myHandler(l, v)
	script o
		property textItemList : missing value
		property foundList : {}
	end script
	
	considering case
		set astid to AppleScript's text item delimiters
		set AppleScript's text item delimiters to return
		set l to return & l -- A text where every item is preceded by a return
		set AppleScript's text item delimiters to return & v
		set o's textItemList to l's text items
		set AppleScript's text item delimiters to astid
		
		repeat with i from 2 to (count o's textItemList)
			set end of o's foundList to v & paragraph 1 of item i of o's textItemList
		end repeat
	end considering
	
	return o's foundList
end myHandler

set fileList to {"3579-08.jpg", "3579.jpg", "3580-08.jpg", "3580.jpg", "3581-08.jpg", "3581.jpg", "3582-08.jpg", "3582.jpg", "3583-04.jpg", "3583.jpg", "3584-04.jpg", "3586-06.jpg", "3588-08.jpg", "3588.jpg", "3590-08.jpg", "3590.jpg", "3591-04.jpg", "3591.jpg"}
set matchVal to "3590"

myHandler(fileList, matchVal)

You’ll need something more thorough if the names in the list don’t all begin with the same number of digits.

Hi Nigel,

Thank you so much for your examples. I remembered Matt Neuburg writing about speeding up list access, but could not find it in my library.

Have a great weekend!

Wow, wow, wow!

Thank you so much for both of your help! And, thanks for the link about speeding up list access. I was looking for a similar page in Rosenthal’s book and did not come up with it. That link explains it well.