I changed it. What if you build the record this way:
set the_rec to {}
set sub_rec to {a:1}
set the_rec to the_rec & sub_rec
set sub_rec to {b:2}
set the_rec to the_rec & sub_rec
set sub_rec to {c:3}
set the_rec to the_rec & sub_rec
return the_rec
This way you can store sub_rec. Is there a way to delete a sub record?
set sub_rec to {a:1}
set end of rec_list to sub_rec
set the_rec to the_rec & sub_rec
set sub_rec to {b:2, c:3}
set end of rec_list to sub_rec
set the_rec to the_rec & sub_rec
set sub_rec to {d:4}
set end of rec_list to sub_rec
set the_rec to the_rec & sub_rec
rec_list
Now I can delete an item from rec_list and rebuild the_rec. Is there a better way to do this?
This sort of thing probably needs to be dealt with on a per-task basis. Working with record lists is super ugly, and there’s really no good way to universally manipulate them. If you have a predictable set of data, it’s easy to simply reconstruct the list from a temporary one and then replace the original list with the edited new version. The following is a modification of my examples of using script objects to handle making references to items in records. I’ve included the code to add items as well, because you need to keep track of what the key’s you’re using are (since applescript can’t do that for you :()…
property theKeyList : {}
property theRecord : {}
set theAction to (button returned of (display dialog "Select an Action:" buttons {"Cancel", "Delete Key", "Add Key"}))
if theAction is "Add Key" then
set theKey to (text returned of (display dialog "Enter Key String:" default answer ""))
set theValue to (text returned of (display dialog ("Enter Value for Key '" & theKey & "':") default answer ""))
addKeyToRecordList(theKey, theValue) --> Add the new key/value pair to theRecord
else if theAction is "Delete Key" then
set theKey to choose from list theKeyList
deleteKeyFromRecordList(theKey) --> Remove the new key/value pair from theRecord
end if
return theRecord
(****** Subroutines ******)
to deleteKeyFromRecordList(theTargetKey)
set theNewRecord to {}
set theNewKeyList to {}
repeat with tmpkey in theKeyList
set tmpkey to (tmpkey as string)
if tmpkey is not (theTargetKey as string) then
copy tmpkey to the end of theNewKeyList
set theNewRecord to (run script "on run{theNewRecord,theRecord}
set theNewRecord to theNewRecord & {" & tmpkey & ":(" & tmpkey & " of theRecord)}
return theNewRecord
end" with parameters {theNewRecord, theRecord})
end if
end repeat
set theKeyList to theNewKeyList
set theRecord to theNewRecord
end deleteKeyFromRecordList
to addKeyToRecordList(theNewKey, theNewValue)
copy theNewKey to the end of theKeyList
set theRecord to (run script "on run{theNewKey, theNewValue, theRecord}
set theRecord to theRecord & {" & theNewKey & ":theNewValue}
return theRecord
end" with parameters {theNewKey, theNewValue, theRecord})
end addKeyToRecordList
This probably isn’t going to be very fast for large or complex record lists, since not only does it have to iterate through them all, it also has to construct a script object for every item so it can rebuild the updated list. Unfortunately, this is required, because it’s really the only way to pass a string as a reference to a key. Ideally, applescript should support references like item named “blah” of theRecord or every key of theRecord. This seems like a huge hole that could be fixed with just a wee bit of work. In every other language, key-value coding is well supported… but not applescript.
I don’t understand how you delete a field from a record. Did you do that in your script?
Sorry, but I read it three times and can’t grasp how you can delete a field from a record.
I’ll read your post again tomorrow when I’m less inibriated.
The thing is, say the data is not predictable. For instance, someone may login from nowhere with some unpridictable data, so you ask the person, “Give me a label” for your data. After the person enters a label, you enter a field in the record with the person’s label and the data is entered as the fields value. This can be done.
This way you can access any data by the label without searching.
I guess that’s the ultimate goal.
But, what if the person’s stuff needs to be deleted. Then how can you delete a field from a record. Note that each field needs to be unique. You know that you can access fields of a record easily,and that’s the good part, but how can you delete fields efficiently? That’s the bad part.
I can make workarounds, but I’m thinking that there might be some trick in deleting fields of records. If anybody knows one then please tell.
You can’t delete properties from records any more than you can delete items from lists. You can create a new record containing all the properties of the old record minus the one you don’t want, though the new record’s structure generally needs to be known at compile-time because that’s when properties get defined.
There are hacks that allow records’ structures to be manipulated at run-time (LNS’s ‘List & Record Tools’ osax, AppleMods’ Record library), but these are fundamentally evil and subject to all sorts of caveats, limitations, uncertainties about reliability, etc. However, the only time I know of where you have to do this is when using LNS’s ‘XML Tools’ osax, which very stupidly stores element attributes as records instead of key-value lists, in which case you have to use their ‘List & Records Tools’ osax to deal with those. Most times when this question comes it, it’s because folk are using the wrong type of object for the job.
Case in point. Records are not associative lists, and trying to treat them as if they were is language abuse. If you want an associative list, use an associative list. AppleScript (unlike most other languages) may not provide a native associative list type, but they’re not that hard to write. AppleMods’ Types library contains a couple of good, robust ones you can use for free, so the easiest thing would be to just nab those.
Thanks for the confirmation. I couldn’t remember if there was a better way of deleting a field from a record. I fell into the trap again, trying to create dynamic fields.