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
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
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
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