more efficient code

Hi all,
I have lots of files that have an abrieviated name (pub_code), using the 4 digit pub_code I would like to lookup its full name, I know I can do this with else if but I have hundreds of different pub_codes and this would make for a very large script. Is there a better way to cross reference the pub_code with the pub_name?

set file_name to "raco123456-jul-10-07.pdf"
set pub_code to characters 1 thru 4 of file_name as string
if pub_code = "raco" then
	set pub_name to "Refrigeration & Air Conditioning"
else if pub_code = "hvns" then
	set pub_name to "Heating & Ventilating News"
	--> and on and on...
end if

Hi,

for a few hundred items I would use a binary search routine and two lists.
This is the fastest way, the two lists needn’t to be sorted alphabetically, but the corrensponding items must be in the same order

property pub_code_List : {"raco", "hvns"}
property pub_name_List : {"Refrigeration & Air Conditioning", "Heating & Ventilating News"}

set file_name to "hvns123456-jul-10-07.pdf"
set pub_name to item BinarySearch(pub_code_List, text 1 thru 4 of file_name) of pub_name_List

on BinarySearch(theList, value)
	local low, mid, high
	script o
		property l : theList
	end script
	
	set low to 1
	set high to (count theList)
	repeat while (low ≤ high)
		set mid to (low + high) div 2
		if ({value} is in items low thru mid of o's l) then
			set high to mid - 1
		else
			set low to mid + 1
		end if
	end repeat
	if (item low of o's l is value) then return low
	return false
end BinarySearch

Hi Stefan,
I don’t doubt for a second that that’ll do exactly what I need but I’m afraid I don’t understand it very well. Your code did give me the idea of comparing lists though. As long as I keep both lists up to date with each other I thought I could use this

set pub_code to "raco"

property pub_code_List : {"raco", "hvns"}
property pub_name_List : {"Refrigeration & Air Conditioning", "Heating & Ventilating News"}

lookup_pub_name(pub_code, pub_code_List, pub_name_List)
on lookup_pub_name(pub_code, pub_code_List, pub_name_List)
	set item_number to 0
	repeat with this_pub_code in pub_code_List
		if this_pub_code contains pub_code then
			set item_number to item_number + 1
			set pub_name to item item_number of pub_name_List
			display dialog pub_name
			return
		else
			set item_number to item_number + 1
		end if
	end repeat
end lookup_pub_name

Do you think that this would cause any problems?
Thanks for your post, I knew you would be able to help :slight_smile:

property pub_code_List : {"raco", "hvns"}
property pub_name_List : {"Refrigeration & Air Conditioning", "Heating & Ventilating News"}

You might try a record, instead:

set pCode to {raco:"Refrigeration & Air Conditioning", hvns:"Heating & Ventilating News"}

pCode's raco --> "Refrigeration & Air Conditioning"

My code does exactly the same as yours, but much faster.
If you have e.g. 250 items and the item you search for is #248,
your script takes 248 loops to find it, my script takes at most 8. (2^8=256)
Binary searching is the most effective way to retrieve data from hugh lists

Oops – my suggestion is NG because it is not trivial to convert the string “raco” into the variable pCode’s raco.

Thanks for the lesson Stefan, I’m glad that my code was working along the right lines at least.
Thanks for your suggestion Adam I may be able to use your example else where.

Best approach for something like this would be to put all your pub data in an external text/plist file where it’s easy to maintain, and have your script read it in at runtime.

If you use a tab-delimited plain text file, searching can be done in various ways. A nice lazy option is to use regular expressions:

property pub_data : ""

set pub_data to read alias "HD:Users:foo:pubdata.txt"
tell application "TextCommands"
	set pub_data to convert linebreaks pub_data to Unix format
end tell

on get_pub_name(pub_code)
	tell application "TextCommands"
		set match_list to (search pub_data for ((escape pattern pub_code) & "\\t(.*)") with regex and individual line matching)
	end tell
	if match_list is {} then error ("Pub code '" & pub_code & "' not found.") number -1728
	return item 1 of match_list
end get_pub_name

get_pub_name("raco")
--> "Refrigeration & Air Conditioning"

If you use an XML plist file, you can easily search that using System Events’ Property List Suite or Satimage’s XMLLib osax, e.g.:

tell application "System Events"
	tell contents of property list file "/users/foo/pubdata.plist"
		set pub_name to value of property list item pub_code
	end tell
end tell

HTH