Collection
Collection · Type
A Collection is a list or dictionary with a toolkit attached: sorting, filtering, summing, grouping and more. You make one with mash.collect(...), and plenty of Foldr gives them to you ready made: a multivalue custom field, the people in a group, mash.users.get("name"), the rows of a lookup. When a script has a set of things to work on, a Collection is usually the right shape for it.
How it works
Section titled “How it works”It holds an array or a dictionary. mash.collect([3, 1, 2]) is a list. mash.collect({ada: 36, bo: 29}) is a dictionary, and its keys are kept. Most methods work the same on both.
Most methods return a new Collection, so they chain. rows.where("dept", "Eng").sortByDesc("pay").pluck("name") reads left to right and leaves rows alone. A few methods change the Collection itself instead: push, put, pull, forget and pop.
Assigning doesn’t copy. set b to a gives the same Collection a second name, so b.push(1) changes a too. Use clone(a) for a copy that shares nothing.
Blocks do the custom work. filter, map, reduce, each, sortBy (with a block) and groupBy take a block that’s run once per item and returns the answer for it.
Sort and filter keep the original keys. A sorted list’s items can show their old positions as keys. Call values() to number them from 0 again.
An empty Collection is still “true”. Test emptiness with isEmpty() or count(), never with if rows.
Common tasks
Section titled “Common tasks”Total and rank a list of dictionaries:
set rows to mash.collect([ {name: "Ada", dept: "Eng", pay: 50}, {name: "Bo", dept: "Ops", pay: 40}, {name: "Cy", dept: "Eng", pay: 70}])printline rows.sum("pay")printline rows.sortByDesc("pay").first()["name"]printline rows.where("dept", "Eng").pluck("name").join(", ")160CyAda, CyFilter with your own test:
set n to mash.collect([5, 3, 8, 1])set big to n.filter(block x return x is more than 2end)printline big.values().join(", ")5, 3, 8Group and count:
set rows to mash.collect([ {name: "Ada", dept: "Eng"}, {name: "Bo", dept: "Ops"}, {name: "Cy", dept: "Eng"}])printline rows.groupBy("dept").map(block g return g.count()end)Collection { "Eng": 2, "Ops": 1}Turn a list into a line of text, or into a plain array:
set n to mash.collect([5, 3, 8])printline n.join("-")printline n.all()[0]5-3-85Work through a multivalue field:
set doc to mash.files.get("Claims", "N1 Claim Form.pdf")set parties to mash.collect(doc.fields["Party"] ?? [])printline parties.join("; ")Watch out for
Section titled “Watch out for”joinandimplodeare the same. Both write the items with a separator between.- Don’t change a Collection while you loop over it. Collect what to change, then change it.
count()andisEmpty()for emptiness, because a Collection is always “true”.- A method name that doesn’t exist raises an error rather than doing nothing. If a call fails with “does not exist”, check the generated list below.
See also
Section titled “See also”Collections and Blocks in the tutorial, and Values and types.
A list with methods, which mash.collect() returns. A plain list or dictionary answers the same methods, so [3, 1, 2].sort() and mash.collect([3, 1, 2]).sort() do the same thing. Where PHP wants a function, MaSH takes a block: items.map(block(item) { return item.size }). Only a block is accepted there, never the name of a PHP function. The methods that change the list are marked.
Methods
Section titled “Methods”collection.add(item: mixed)
Adds an item to the end. On a list or dictionary held in a variable it changes that variable in place: list.push(3) is enough, there is no need to assign the result.
collection.all()
Returns the items as a plain list or dictionary.
average
Section titled “average”collection.average(callback?: mixed)
The same as avg.
collection.avg(callback?: mixed)
The average of the numbers, or of one field of each item: avg(“price”).
collection.chunk(size: mixed)
Splits the items into groups of the size you give. The last group may be smaller.
collapse
Section titled “collapse”collection.collapse()
Joins a list of lists into one flat list.
combine
Section titled “combine”collection.combine(values: mixed)
Uses the items as keys and the list you give as their values, and returns the dictionary.
concat
Section titled “concat”collection.concat(source: mixed)
Adds the items of another list to the end.
contains
Section titled “contains”collection.contains(key: mixed, operator?: mixed, value?: mixed)
True when a value is in it. With a block, true when the block returns true for any item.
collection.count() → int
The number of items.
countBy
Section titled “countBy”collection.countBy(countBy?: mixed)
Counts how often each value turns up. With a block, counts by what the block returns.
collection.diff(items: mixed)
The items that are not in the other list.
diffKeys
Section titled “diffKeys”collection.diffKeys(items: mixed)
The items whose keys are not in the other dictionary.
doesntContain
Section titled “doesntContain”collection.doesntContain(key: mixed, operator?: mixed, value?: mixed)
True when a value is not in it. With a block, true when the block returns true for no item.
duplicates
Section titled “duplicates”collection.duplicates(callback?: mixed, strict?: mixed)
The values that appear more than once.
collection.each(callback: block)
Runs the block on each item. Return false from it to stop.
collection.every(key: mixed, operator?: mixed, value?: mixed)
True when the block returns true for every item.
except
Section titled “except”collection.except(keys: mixed)
Everything except the keys you name.
filter
Section titled “filter”collection.filter(callback?: block)
Keeps the items the block returns true for. With no block, drops empty values.
collection.first(callback?: block, default?: mixed)
The first item. With a block, the first item the block returns true for.
firstWhere
Section titled “firstWhere”collection.firstWhere(key: mixed, operator?: mixed, value?: mixed)
The first item whose field has the value: firstWhere(“type”, “pdf”).
flatMap
Section titled “flatMap”collection.flatMap(callback: block)
Runs the block on each item, then flattens the results one level.
flatten
Section titled “flatten”collection.flatten(depth?: mixed)
Flattens nested lists into one.
collection.flip()
Swaps the keys and the values.
forget
Section titled “forget”collection.forget(keys: mixed)
Removes the item at a key. On a list or dictionary held in a variable it changes that variable in place: list.push(3) is enough, there is no need to assign the result.
collection.get(key: mixed, default?: mixed)
The value at a key, or the default you give when it is not there.
groupBy
Section titled “groupBy”collection.groupBy(groupBy: mixed, preserveKeys?: mixed)
Groups the items by a field, or by what the block returns, into a dictionary of lists.
collection.has(key: mixed)
True when the key exists.
implode
Section titled “implode”collection.implode(value: mixed, glue?: mixed)
Joins the values into one string with the separator you give.
intersect
Section titled “intersect”collection.intersect(items: mixed)
Keeps only the items that are also in the other list.
intersectByKeys
Section titled “intersectByKeys”collection.intersectByKeys(items: mixed)
Keeps only the items whose keys are also in the other dictionary.
isEmpty
Section titled “isEmpty”collection.isEmpty()
True when there are no items.
isNotEmpty
Section titled “isNotEmpty”collection.isNotEmpty()
True when there is at least one item.
collection.join(glue: mixed, finalGlue?: mixed)
Joins the values into a string, with an optional different separator before the last.
collection.keyBy(keyBy: mixed)
Re-keys the items by a field, or by what the block returns.
collection.keys()
The keys.
collection.last(callback?: block, default?: mixed)
The last item. With a block, the last item the block returns true for.
collection.map(callback: block)
Runs the block on each item and returns the results.
mapWithKeys
Section titled “mapWithKeys”collection.mapWithKeys(callback: block)
Runs the block on each item. The block returns a one-entry dictionary, and they are merged into one.
collection.max(callback?: mixed)
The largest value, or the largest of one field.
median
Section titled “median”collection.median(key?: mixed)
The middle value, or the middle of one field.
collection.merge(items: mixed)
Adds the items of another dictionary or list. A key that exists is overwritten.
mergeRecursive
Section titled “mergeRecursive”collection.mergeRecursive(items: mixed)
Like merge, but a key that exists in both and holds a list has the two lists joined.
collection.min(callback?: mixed)
The smallest value, or the smallest of one field.
collection.only(keys: mixed)
Keeps only the keys you name.
collection.pad(size: mixed, value: mixed)
Fills the list with a value up to a size. A negative size pads at the start.
partition
Section titled “partition”collection.partition(key: mixed, operator?: mixed, value?: mixed)
Splits the items into two lists: those the block returns true for, and the rest.
collection.pluck(value: mixed, key?: mixed)
The value of one field from each item: pluck(“name”).
prepend
Section titled “prepend”collection.prepend(value: mixed, key?: mixed)
Adds an item to the start. On a list or dictionary held in a variable it changes that variable in place: list.push(3) is enough, there is no need to assign the result.
collection.push(values?: mixed)
Adds an item to the end. On a list or dictionary held in a variable it changes that variable in place: list.push(3) is enough, there is no need to assign the result.
collection.put(key: mixed, value: mixed)
Sets the item at a key. On a list or dictionary held in a variable it changes that variable in place: list.push(3) is enough, there is no need to assign the result.
random
Section titled “random”collection.random(number?: mixed, preserveKeys?: mixed)
A random item. Give a number to get that many.
reduce
Section titled “reduce”collection.reduce(callback: block, initial?: mixed)
Runs the block on each item with the running result, and returns the final result.
reject
Section titled “reject”collection.reject(callback?: mixed)
Drops the items the block returns true for.
remove
Section titled “remove”collection.remove(keys: mixed)
Removes the item at a key. On a list or dictionary held in a variable it changes that variable in place: list.push(3) is enough, there is no need to assign the result.
reverse
Section titled “reverse”collection.reverse()
The items in the opposite order.
search
Section titled “search”collection.search(value: mixed, strict?: mixed)
The key of the first item with the value (or that the block returns true for), or false.
shuffle
Section titled “shuffle”collection.shuffle(seed?: mixed)
The items in a random order.
collection.skip(count: mixed)
Everything after the first n items.
collection.slice(offset: mixed, length?: mixed)
A part of the list, from an offset, with an optional length.
collection.sort(callback?: mixed)
Sorted low to high. With a block, the block compares two items.
sortBy
Section titled “sortBy”collection.sortBy(callback: mixed, options?: mixed, descending?: mixed)
Sorted by a field, or by what the block returns, low to high.
sortByDesc
Section titled “sortByDesc”collection.sortByDesc(callback: mixed, options?: mixed)
Sorted by a field, or by what the block returns, high to low.
sortDesc
Section titled “sortDesc”collection.sortDesc(options?: mixed)
Sorted high to low.
sortKeys
Section titled “sortKeys”collection.sortKeys(options?: mixed, descending?: mixed)
Sorted by key, low to high.
sortKeysDesc
Section titled “sortKeysDesc”collection.sortKeysDesc(options?: mixed)
Sorted by key, high to low.
collection.sum(callback?: mixed)
The total of the numbers, or of one field of each item.
collection.take(limit: mixed)
The first n items. A negative n takes from the end.
toArray
Section titled “toArray”collection.toArray()
Returns the items as a plain list or dictionary.
unique
Section titled “unique”collection.unique(key?: mixed, strict?: mixed)
Drops repeated values. Give a field to compare by.
values
Section titled “values”collection.values()
The values, with the keys replaced by 0, 1, 2 and so on.
collection.where(key: mixed, operator?: mixed, value?: mixed)
Keeps the items whose field matches: where(“size”, ”>”, 100), or where(“type”, “pdf”).
whereIn
Section titled “whereIn”collection.whereIn(key: mixed, values: mixed, strict?: mixed)
Keeps the items whose field is one of the values you give.
whereNotIn
Section titled “whereNotIn”collection.whereNotIn(key: mixed, values: mixed, strict?: mixed)
Keeps the items whose field is none of the values you give.
collection.zip(items: mixed)
Pairs each item with the item at the same place in another list.