# Functions
Dataview functions provide more advanced ways to manipulate data. You can use functions **in [data commands](https://blacksmithgu.github.io/obsidian-dataview/queries/data-commands/)** (except FROM) to filter or group or use them **as [additional information](https://blacksmithgu.github.io/obsidian-dataview/queries/query-types/)** like TABLE columns or extra output for LIST queries to see your data in a new light.
## How functions work
Functions are another form of [expression](https://blacksmithgu.github.io/obsidian-dataview/reference/expressions/) and can be used everywhere you can use an expression. A function always gives you back a new value and follows this format:
`functionname(parameter1, parameter2)`
Parameters are again [expressions](https://blacksmithgu.github.io/obsidian-dataview/reference/expressions/) and you can use literals, meta data fields, or even another function as parameter. You'll find out which [data type](https://blacksmithgu.github.io/obsidian-dataview/annotation/types-of-metadata/) your parameters need to have on the documentation of this page. Pay attention to the information inside the function brackets. Parameters in square brackets, i.e. `link(path, [display])` means they are _optional_ and can be omitted. Find out more about the default behaviour of each function on their explanation.
## Calling functions on lists of values
Most functions can be applied either to single values (like `number`, `string`, `date`, etc.) OR to lists of those values. If a function is applied to a list, it also returns a list after the function is applied to each element in the list. For example:
`lower("YES") = "yes" lower(["YES", "NO"]) = ["yes", "no"] replace("yes", "e", "a") = "yas" replace(["yes", "ree"], "e", "a") = ["yas", "raa"]`
This so-called "function vectorization" will not be mentioned explicitly on the following definitions and is possible for a wide range of these functionalities implicitly.
## Constructors
Constructors which create values.
### `object(key1, value1, …)`
Creates a new object with the given keys and values. Keys and values should alternate in the call, and keys should always be strings/text.
`object() => empty object object("a", 6) => object which maps "a" to 6 object("a", 4, "c", "yes") => object which maps a to 4, and c to "yes"`
### `list(value1, value2, …)`
Creates a new list with the given values in it.
`list() => empty list list(1, 2, 3) => list with 1, 2, and 3 list("a", "b", "c") => list with "a", "b", and "c"`
### `date(any)`
Parses a date from the provided string, date, or link object, if possible, returning null otherwise.
`date("2020-04-18") = <date object representing April 18th, 2020> date([[2021-04-16]]) = <date object for the given page, referring to file.day>`
### `date(text, format)`
Parses a date from text to luxon `DateTime` with the specified format. Note localised formats might not work. Uses [Luxon tokens](https://moment.github.io/luxon/#/formatting?id=table-of-tokens).
`date("12/31/2022", "MM/dd/yyyy") => DateTime for Decemeber 31th, 2022 date("210313", "yyMMdd") => DateTime for March 13th, 2021 date("946778645000", "x") => DateTime for "2000-01-02T03:04:05"`
### `dur(any)`
Parses a duration from the provided string or duration, returning null on failure.
`dur(8 minutes) = <8 minutes> dur("8 minutes, 4 seconds") = <8 minutes, 4 seconds> dur(dur(8 minutes)) = dur(8 minutes) = <8 minutes>`
### `number(string)`
Pulls the first number out of the given string, returning it if possible. Returns null if there are no numbers in the string.
`number("18 years") = 18 number(34) = 34 number("hmm") = null`
### `string(any)`
Converts any value into a "reasonable" string representation. This sometimes produces less pretty results than just directly using the value in a query - it is mostly useful for coercing dates, durations, numbers, and so on into strings for manipulation.
`string(18) = "18" string(dur(8 hours)) = "8 hours" string(date(2021-08-15)) = "August 15th, 2021"`
### `link(path, [display])`
Construct a link object from the given file path or name. If provided with two arguments, the second argument is the display name for the link.
`link("Hello") => link to page named 'Hello' link("Hello", "Goodbye") => link to page named 'Hello', displays as 'Goodbye'`
### `embed(link, [embed?])`
Convert a link object into an embedded link; support for embedded links is somewhat spotty in Dataview views, though embedding of images should work.
`embed(link("Hello.png")) => embedded link to the "Hello.png" image, which will render as an actual image.`
### `elink(url, [display])`
Construct a link to an external url (like `www.google.com`). If provided with two arguments, the second argument is the display name for the link.
`elink("www.google.com") => link element to google.com elink("www.google.com", "Google") => link element to google.com, displays as "Google"`
### `typeof(any)`
Get the type of any object for inspection. Can be used in conjunction with other operators to change behavior based on type.
`typeof(8) => "number" typeof("text") => "string" typeof([1, 2, 3]) => "array" typeof({ a: 1, b: 2 }) => "object" typeof(date(2020-01-01)) => "date" typeof(dur(8 minutes)) => "duration"`
---
## Numeric Operations
### `round(number, [digits])`
Round a number to a given number of digits. If the second argument is not specified, rounds to the nearest whole number; otherwise, rounds to the given number of digits.
`round(16.555555) = 7 round(16.555555, 2) = 16.56`
### `trunc(number)`
Truncates ("cuts off") the decimal point from a number.
`trunc(12.937) = 12 trunc(-93.33333) = -93 trunc(-0.837764) = 0`
### `floor(number)`
Always rounds down and returns the largest integer less than or equal to a given number. This means that negative numbers become more negative.
`floor(12.937) = 12 floor(-93.33333) = -94 floor(-0.837764) = -1`
### `ceil(number)`
Always rounds up and returns the smallest integer greater than or equal to a given number. This means negative numbers become less negative.
`ceil(12.937) = 13 ceil(-93.33333) = -93 ceil(-0.837764) = 0`
### `min(a, b, ..)`
Compute the minimum value of a list of arguments, or an array.
`min(1, 2, 3) = 1 min([1, 2, 3]) = 1 min("a", "ab", "abc") = "a"`
### `max(a, b, …)`
Compute the maximum value of a list of arguments, or an array.
`max(1, 2, 3) = 3 max([1, 2, 3]) = 3 max("a", "ab", "abc") = "abc"`
### `sum(array)`
Sums all numeric values in the array. If you have null values in your average, you can eliminate them via the `nonnull` function.
`sum([1, 2, 3]) = 6 sum([]) = null sum(nonnull([null, 1, 8])) = 9`
### `product(array)`
Calculates the product of a list of numbers. If you have null values in your average, you can eliminate them via the `nonnull` function.
`product([1,2,3]) = 6 product([]) = null product(nonnull([null, 1, 2, 4])) = 8`
### `average(array)`
Computes the numeric average of numeric values. If you have null values in your average, you can eliminate them via the `nonnull` function.
`average([1, 2, 3]) = 2 average([]) = null average(nonnull([null, 1, 2])) = 1.5`
### `minby(array, function)`
Compute the minimum value of an array, using the provided function.
`minby([1, 2, 3], (k) => k) = 1 minby([1, 2, 3], (k) => 0 - k) => 3 minby(this.file.tasks, (k) => k.due) => (earliest due)`
### `maxby(array, function)`
Compute the maximum value of an array, using the provided function.
`maxby([1, 2, 3], (k) => k) = 3 maxby([1, 2, 3], (k) => 0 - k) => 1 maxby(this.file.tasks, (k) => k.due) => (latest due)`
--
## Objects, Arrays, and String Operations
Operations that manipulate values inside of container objects.
### `contains()` and friends
For a quick summary, here are some examples:
`contains("Hello", "Lo") = false contains("Hello", "lo") = true icontains("Hello", "Lo") = true icontains("Hello", "lo") = true econtains("Hello", "Lo") = false econtains("Hello", "lo") = true econtains(["this","is","example"], "ex") = false econtains(["this","is","example"], "is") = true`
#### `contains(object|list|string, value)`
Checks if the given container type has the given value in it. This function behave slightly differently based on whether the first argument is an object, a list, or a string. This function is case-sensitive.
- For objects, checks if the object has a key with the given name. For example,
`contains(file, "ctime") = true contains(file, "day") = true (if file has a date in its title, false otherwise)`
- For lists, checks if any of the array elements equals the given value. For example,
`contains(list(1, 2, 3), 3) = true contains(list(), 1) = false`
- For strings, checks if the given value is a substring (i.e., inside) the string.
`contains("hello", "lo") = true contains("yes", "no") = false`
#### `icontains(object|list|string, value)`
Case insensitive version of `contains()`.
#### `econtains(object|list|string, value)`
"Exact contains" checks if the exact match is found in the string/list. This function is case sensitive.
- For strings, it behaves exactly like [`contains()`](https://blacksmithgu.github.io/obsidian-dataview/reference/functions/#containsobjectliststring-value).
`econtains("Hello", "Lo") = false econtains("Hello", "lo") = true`
- For lists, it checks if the exact word is in the list.
`econtains(["These", "are", "words"], "word") = false econtains(["These", "are", "words"], "words") = true`
- For objects, it checks if the exact key name is present in the object. It does **not** do recursive checks.
`econtains({key:"value", pairs:"here"}, "here") = false econtains({key:"value", pairs:"here"}, "key") = true econtains({key:"value", recur:{recurkey: "val"}}, "value") = false econtains({key:"value", recur:{recurkey: "val"}}, "Recur") = false econtains({key:"value", recur:{recurkey: "val"}}, "recurkey") = false`
### `containsword(list|string, value)`
Checks if `value` has an exact word match in `string` or `list`. This is case insensitive. The outputs are different for different types of input, see examples.
- For strings, it checks if the word is present in the given string.
`containsword("word", "word") = true containsword("word", "Word") = true containsword("words", "Word") = false containsword("Hello there!, "hello") = true containsword("Hello there!, "HeLLo") = true containsword("Hello there chaps!, "chap") = false containsword("Hello there chaps!, "chaps") = true`
- For lists, it returns a list of booleans indicating if the word's exact case insensitive match was found.
`containsword(["I have no words.", "words"], "Word") = [false, false] containsword(["word", "Words"], "Word") = [true, false] containsword(["Word", "Words in word"], "WORD") = [true, true]`
### `extract(object, key1, key2, …)`
Pulls multiple fields out of an object, creating a new object with just those fields.
`extract(file, "ctime", "mtime") = object("ctime", file.ctime, "mtime", file.mtime) extract(object("test", 1)) = object()`
### `sort(list)`
Sorts a list, returning a new list in sorted order.
`sort(list(3, 2, 1)) = list(1, 2, 3) sort(list("a", "b", "aa")) = list("a", "aa", "b")`
### `reverse(list)`
Reverses a list, returning a new list in reversed order.
`reverse(list(1, 2, 3)) = list(3, 2, 1) reverse(list("a", "b", "c")) = list("c", "b", "a")`
### `length(object|array)`
Returns the number of fields in an object, or the number of entries in an array.
`length([]) = 0 length([1, 2, 3]) = 3 length(object("hello", 1, "goodbye", 2)) = 2`
### `nonnull(array)`
Return a new array with all null values removed.
`nonnull([]) = [] nonnull([null, false]) = [false] nonnull([1, 2, 3]) = [1, 2, 3]`
### `all(array)`
Returns `true` only if ALL values in the array are truthy. You can also pass multiple arguments to this function, in which case it returns `true` only if all arguments are truthy.
`all([1, 2, 3]) = true all([true, false]) = false all(true, false) = false all(true, true, true) = true`
You can pass a function as second argument to return only true if all elements in the array matches the predicate.
`all([1, 2, 3], (x) => x > 0) = true all([1, 2, 3], (x) => x > 1) = false all(["apple", "pie", 3], (x) => typeof(x) = "string") = false`
### `any(array)`
Returns `true` if ANY of the values in the array are truthy. You can also pass multiple arguments to this function, in which case it returns `true` if any of the arguments are truthy.
`any(list(1, 2, 3)) = true any(list(true, false)) = true any(list(false, false, false)) = false any(true, false) = true any(false, false) = false`
You can pass a function as second argument to return only true if any element in the array matches the predicate.
`any(list(1, 2, 3), (x) => x > 2) = true any(list(1, 2, 3), (x) => x = 0) = false`
### `none(array)`
Returns `true` if NONE of the values in the array are truthy.
`none([]) = true none([false, false]) = true none([false, true]) = false none([1, 2, 3]) = false`
You can pass a function as second argument to return only true if none of the elements in the array matches the predicate.
`none([1, 2, 3], (x) => x = 0) = true none([true, true], (x) => x = false) = true none(["Apple", "Pi", "Banana"], (x) => startswith(x, "A")) = false`
### `join(array, [delimiter])`
Joins elements in an array into a single string (i.e., rendering them all on the same line). If provided with a second argument, then each element will be separated by the given separator.
`join(list(1, 2, 3)) = "1, 2, 3" join(list(1, 2, 3), " ") = "1 2 3" join(6) = "6" join(list()) = ""`
### `filter(array, predicate)`
Filters elements in an array according to the predicate, returning a new list of the elements which matched.
`filter([1, 2, 3], (x) => x >= 2) = [2, 3] filter(["yes", "no", "yas"], (x) => startswith(x, "y")) = ["yes", "yas"]`
### `map(array, func)`
Applies the function to each element in the array, returning a list of the mapped results.
`map([1, 2, 3], (x) => x + 2) = [3, 4, 5] map(["yes", "no"], (x) => x + "?") = ["yes?", "no?"]`
### `flat(array, [depth])`
Concatenates sub-levels of the array to the desired depth. Default is 1 level, but it can concatenate multiple levels. E.g. Can be used to reduce array depth on `rows` lists after doing `GROUP BY`.
`flat(list(1, 2, 3, list(4, 5), 6)) => list(1, 2, 3, 4, 5, 6) flat(list(1, list(21, 22), list(list (311, 312, 313))), 4) => list(1, 21, 22, 311, 312, 313) flat(rows.file.outlinks)) => All the file outlinks at first level in output`
---
## String Operations
### `regextest(pattern, string)`
Checks if the given regex pattern can be found in the string (using the JavaScript regex engine).
`regextest("\w+", "hello") = true regextest(".", "a") = true regextest("yes|no", "maybe") = false regextest("what", "what's up dog?") = true`
### `regexmatch(pattern, string)`
Checks if the given regex pattern matches the _entire_ string, using the JavaScript regex engine. This differs from `regextest` in that regextest can match just parts of the text.
`regexmatch("\w+", "hello") = true regexmatch(".", "a") = true regexmatch("yes|no", "maybe") = false regexmatch("what", "what's up dog?") = false`
### `regexreplace(string, pattern, replacement)`
Replaces all instances where the _regex_ `pattern` matches in `string`, with `replacement`. This uses the JavaScript replace method under the hood, so you can use special characters like `$1` to refer to the first capture group, and so on.
`regexreplace("yes", "[ys]", "a") = "aea" regexreplace("Suite 1000", "\d+", "-") = "Suite -"`
### `replace(string, pattern, replacement)`
Replace all instances of `pattern` in `string` with `replacement`.
`replace("what", "wh", "h") = "hat" replace("The big dog chased the big cat.", "big", "small") = "The small dog chased the small cat." replace("test", "test", "no") = "no"`
### `lower(string)`
Convert a string to all lower case.
`lower("Test") = "test" lower("TEST") = "test"`
### `upper(string)`
Convert a string to all upper case.
`upper("Test") = "TEST" upper("test") = "TEST"`
### `split(string, delimiter, [limit])`
Split a string on the given delimiter string. If a third argument is provided, it limits the number of splits that occur. The delimiter string is interpreted as a regular expression. If there are capture groups in the delimiter, matches are spliced into the result array, and non-matching captures are empty strings.
`split("hello world", " ") = list("hello", "world") split("hello world", "\s") = list("hello", "world") split("hello there world", " ", 2) = list("hello", "there") split("hello there world", "(t?here)") = list("hello ", "there", " world") split("hello there world", "( )(x)?") = list("hello", " ", "", "there", " ", "", "world")`
### `startswith(string, prefix)`
Checks if a string starts with the given prefix.
`startswith("yes", "ye") = true startswith("path/to/something", "path/") = true startswith("yes", "no") = false`
### `endswith(string, suffix)`
Checks if a string ends with the given suffix.
`endswith("yes", "es") = true endswith("path/to/something", "something") = true endswith("yes", "ye") = false`
### `padleft(string, length, [padding])`
Pads a string up to the desired length by adding padding on the left side. If you omit the padding character, spaces will be used by default.
`padleft("hello", 7) = " hello" padleft("yes", 5, "!") = "!!yes"`
### `padright(string, length, [padding])`
Equivalent to `padleft`, but pads to the right instead.
`padright("hello", 7) = "hello " padright("yes", 5, "!") = "yes!!"`
### `substring(string, start, [end])`
Take a slice of a string, starting at `start` and ending at `end` (or the end of the string if unspecified).
`substring("hello", 0, 2) = "he" substring("hello", 2, 4) = "ll" substring("hello", 2) = "llo" substring("hello", 0) = "hello"`
### `truncate(string, length, [suffix])`
Truncate a string to be at most the given length, including the `suffix` (which defaults to `…`). Generally useful to cut off long text in tables.
`truncate("Hello there!", 8) = "Hello…" truncate("Hello there!", 8, "/") = "Hello t/" truncate("Hello there!", 10) = "Hello t…" truncate("Hello there!", 10, "!") = "Hello the!" truncate("Hello there!", 20) = "Hello there!"`
## Utility Functions
### `default(field, value)`
If `field` is null, return `value`; otherwise return `field`. Useful for replacing null values with defaults. For example, to show projects which haven't been completed yet, use `"incomplete"` as their default value:
`default(dateCompleted, "incomplete")`
Default is vectorized in both arguments; if you need to use default explicitly on a list argument, use `ldefault`, which is the same as default but is not vectorized.
`default(list(1, 2, null), 3) = list(1, 2, 3) ldefault(list(1, 2, null), 3) = list(1, 2, null)`
### `choice(bool, left, right)`
A primitive if statement - if the first argument is truthy, returns left; otherwise, returns right.
`choice(true, "yes", "no") = "yes" choice(false, "yes", "no") = "no" choice(x > 4, y, z) = y if x > 4, else z`
### `striptime(date)`
Strip the time component of a date, leaving only the year, month, and day. Good for date comparisons if you don't care about the time.
`striptime(file.ctime) = Created striptime(file.mtime) = file.mday`
### `dateformat(date|datetime, string)`
Format a Dataview date using a formatting string. Uses [Luxon tokens](https://moment.github.io/luxon/#/formatting?id=table-of-tokens).
`dateformat(file.ctime,"yyyy-MM-dd") = "2022-01-05" dateformat(file.ctime,"HH:mm:ss") = "12:18:04" dateformat(date(now),"x") = "1407287224054" dateformat(file.mtime,"ffff") = "Wednesday, August 6, 2014, 1:07 PM Eastern Daylight Time"`
### `durationformat(duration, string)`
Format a Dataview duration using a formatting string. Anything inside single quotes will not be treated as a token and instead will be shown in the output as written. See examples.
You may use these tokens:
- `S` for milliseconds
- `s` for seconds
- `m` for minutes
- `h` for hours
- `d` for days
- `w` for weeks
- `M` for months
- `y` for years
`durationformat(dur("3 days 7 hours 43 seconds"), "ddd'd' hh'h' ss's'") = "003d 07h 43s" durationformat(dur("365 days 5 hours 49 minutes"), "yyyy ddd hh mm ss") = "0001 000 05 49 00" durationformat(dur("2000 years"), "M months") = "24000 months" durationformat(dur("14d"), "s 'seconds'") = "1209600 seconds"`
### `localtime(date)`
Converts a date in a fixed timezone to a date in the current timezone.
### `meta(link)`
Get an object containing metadata of a link. When you access a property on a link what you get back is the property value from the linked file. The `meta` function makes it possible to access properties of the link itself.
There are several properties on the object returned by `meta`:
#### `meta(link).display`
Get the display text of a link, or null if the link does not have defined display text.
`meta([[2021-11-01|Displayed link text]]).display = "Displayed link text" meta([[2021-11-01]]).display = null`
#### `meta(link).embed`
True or false depending on whether the link is an embed. Those are links that begin with an exclamation mark, like `![[Some Link]]`.
#### `meta(link).path`
Get the path portion of a link.
`meta([[My Project]]).path = "My Project" meta([[My Project#Next Actions]]).path = "My Project" meta([[My Project#^9bcbe8]]).path = "My Project"`
#### `meta(link).subpath`
Get the subpath of a link. For links to a heading within a file the subpath will be the text of the heading. For links to a block the subpath will be the block ID. If neither of those cases applies then the subpath will be null.
`meta([[My Project#Next Actions]]).subpath = "Next Actions" meta([[My Project#^9bcbe8]]).subpath = "9bcbe8" meta([[My Project]]).subpath = null`
This can be used to select tasks under specific headings.
` ```dataview task where meta(section).subpath = "Next Actions" ``` `
#### `meta(link).type`
Has the value "file", "header", or "block" depending on whether the link links to an entire file, a heading within a file, or to a block within a file.
`meta([[My Project]]).type = "file" meta([[My Project#Next Actions]]).type = "header" meta([[My Project#^9bcbe8]]).type = "block"`