How to write and read a record with unknown elements

I get a list of parts of filenames from a folder. I want to count the occurrences of a set of combinations, here represented by fruit. My first problem is that I don’t know how to add the new element to the record from a variable like this:


set theRecord to {}
set theList to {"Apple", "Banana", "Banana", "Banana", "Orange", "Orange"}

repeat with theItem in theList
	try
		set theItem of theRecord to (theItem of theRecord) + 1
	on error
		set theRecord to theRecord & {theItem:1}
	end try
end repeat

I want theRecord to be {Apple:1, Banana:3, Orange:2}, but get {theItem:6}

My second problem is that I don’t know how to get the elements from the record (if I fill it “manually”}, only the values.

I have a feeling I am doing it in a backwards way here. Working with records is a somewhat new experience to me.

If you AppleScript Toolbox installed:

set theRecord to {}
set theList to {"Apple", "Banana", "Banana", "Banana", "Orange", "Orange"}

set theKeyWords to makeUnique(theList)
repeat with theKeyWord in theKeyWords
	set end of theRecord to contents of theKeyWord
	set end of theRecord to 0
end repeat

repeat with fruit in theList
	repeat with i from 1 to (count theRecord) by 2
		if item i of theRecord = contents of fruit then
			set item (i + 1) of theRecord to (item (i + 1) of theRecord) + 1
		end if
	end repeat
end repeat

--coerce the list to an record 
set theRecord to «class seld» of (record {«class usrf»:theRecord} as record)

on makeUnique(lst)
	set newList to {}
	repeat with i from 1 to count lst
		if item i of lst is not in newList then
			set end of newList to item i of lst
		end if
	end repeat
	return newList
end makeUnique

With vanilla and of the box AppleScript you can not (it can with AppleScriptObjC, osaxen or faceless scriptable background apps). But you can also use default values like by concatenating a default values behind it when retreiving:

set theRecord to {Apple:1, Banana:3, Orange:2}

--check to see how many pears are in there:
set nrOfPears to Pear of (theRecord & {Pear:0})
set nrOfApples to Apple of (theRecord & {Apple:0})
return {nrOfPears, nrOfApples}

Great! That is not exactly what I asked for, but it might actually be even better!
Thank you!

Hello,

I’m not sure to understand but if I’m not wrong about your question, there is a ruse to retrieve the full content of the record, so its labels (the elements?) by catching an error:


try
	set recordElements to label of theRecord -- or any expression that can compile without error but can't actually run
on error errMsg
	set text item delimiters to {"{", "}"}
	set allProperties to text item 2 of errMsg
end try
set text item delimiters to ""
allProperties -- returns "Apple:1, Banana:3, Orange:2" 

Be aware that this trick ran on an old Applescript version (Lion), not sure it could with recent versions

If you are running 10.9 or later, here’s an alternative. It uses a class known as a counted set, which holds each value only once, but also keeps track the number of times each value is added to the set.

use scripting additions
use framework "Foundation"

set theList to {"Apple", "Banana", "Banana", "Banana", "Orange", "Orange"}
set theDict to current application's NSMutableDictionary's |dictionary|() -- dictionary/record to store values in
set theSet to current application's NSCountedSet's setWithArray:theList
set theEnumerator to theSet's objectEnumerator()
repeat
	set aKey to theEnumerator's nextObject()
	if aKey = missing value then exit repeat -- no more entries
	theDict's setObject:(theSet's countForObject:aKey) forKey:aKey
end repeat
theDict as record
-->	{Apple:1, Banana:3, Orange:2}

if you’re running 10.9, it needs to be put in a script library.

Fantastic tips! Thank you very much. If not now this will come in handy anytime soon. :slight_smile: