FEEL list functions: list contains, sum, count, sort, filter and more
FEEL guide · 26 built-in functions · DMN 1.6
Lists are how a DMN decision deals with more than one of anything: order lines, applicants, past claims. FEEL lists are ordered, can hold values of any type including null and other lists, and are never modified. Every list function returns a new list.
This guide covers every list built-in, plus the patterns you need around them: summing a field across a list of contexts, filtering out nulls before aggregating, and when to use list contains and when in. Each result was computed by the FEEL engine behind the evaluator at the top.
All FEEL list functions at a glance
| Function | Signature | Returns |
|---|---|---|
| list contains | list contains(list, element) | Returns true if the list contains the element |
| count | count(list) | Returns the number of elements in the list |
| min | min(list) or min(c1, …, cN) | Returns the smallest element |
| max | max(list) or max(c1, …, cN) | Returns the largest element |
| sum | sum(list) or sum(n1, …, nN) | Returns the sum of the numbers |
| mean | mean(list) or mean(n1, …, nN) | Returns the arithmetic average of the numbers; null for an empty list |
| median | median(list) or median(n1, …, nN) | Returns the median: the middle element of the sorted values, or the mean of the two middle elements for an even count |
| stddev | stddev(list) or stddev(n1, …, nN) | Returns the sample standard deviation of the numbers |
| mode | mode(list) or mode(n1, …, nN) | Returns the most frequent value(s) as a list; ties produce several results in ascending order |
| all | all(list) or all(b1, …, bN) | Returns true if every element is true, false if any element is false, and null otherwise |
| any | any(list) or any(b1, …, bN) | Returns true if at least one element is true, false if all are false, and null otherwise |
| sublist | sublist(list, start position, length?) | Returns the slice of the list starting at start position, running to the end or for length elements |
| append | append(list, item…) | Returns a new list with the items added to the end |
| concatenate | concatenate(list…) | Returns one list containing the elements of all argument lists, in order |
| insert before | insert before(list, position, newItem) | Returns a new list with newItem inserted before the given position |
| remove | remove(list, position) | Returns a new list with the element at the given position removed |
| reverse | reverse(list) | Returns the list in reverse order |
| index of | index of(list, match) | Returns the positions of all occurrences of match, as an ascending list of 1-based indexes |
| union | union(list…) | Returns all elements of the argument lists with duplicates removed, preserving first-seen order |
| distinct values | distinct values(list) | Returns the list with duplicate elements removed, preserving first-seen order |
| duplicate values | duplicate values(list) | Returns the values that appear more than once in the list |
| flatten | flatten(list) | Returns a flat list with all nested lists recursively expanded in place |
| product | product(list) or product(n1, …, nN) | Returns the product of the numbers |
| sort | sort(list, precedes) | Returns the list sorted by the precedes function |
| list replace | list replace(list, position | match, newItem) | Returns a new list with the element at the position, or every element accepted by the matcher function, replaced by newItem |
| partition | partition(list, size) | Splits the list into consecutive chunks of the given size; the last chunk may be shorter |
Rules every list function follows
Positions are 1-based, and negative positions count from the end. A position must exist in the list: 0 or anything beyond the length is outside the function's domain, and the result is null. The same goes for a sublist length that runs past the end of the list.
A single value counts as a one-element list. Where a function expects a list, FEEL converts a single value into a list with that one element, so count("abc") is 1 and sum(5) is 5.
Aggregates do not skip nulls. sum, mean, min, max and the others return null if any element is null. Filter the list first with [item != null].
Summing and counting over a list of contexts
Decision inputs are usually lists of contexts, such as order lines with a price and a quantity. Selecting a field from a list of contexts gives the list of that field's values, so sum(lines.price) works directly. For anything more than one field, use a for expression, and add a filter to count only matching entries.
sum([{price: 2, qty: 3}, {price: 5, qty: 1}].price)
.price on a list of contexts gives the list of prices.
sum(for line in [{price: 2, qty: 3}, {price: 5, qty: 1}] return line.price * line.qty)
Line totals: price times quantity, summed.
count([{age: 17}, {age: 34}, {age: 52}][age >= 18])
Inside a filter, the fields of each context are in scope directly.
max([{age: 17}, {age: 34}, {age: 52}].age)
list contains, in and =
list contains(list, x) and the in operator both test membership, and both find a null element, because null = null is true. Neither converts types, so the string "2" is not found in a list of numbers. Numbers compare by value, so 1 and 1.0 are equal.
list contains([1, null, 3], null)
2 in [1, 2, 3]
null in [1, null, 3]
Combining lists: append, concatenate, union, flatten
append adds its arguments as elements, so appending a list nests it. concatenate joins lists end to end. union also joins them but drops duplicates. flatten removes nesting at every depth.
concatenate([1], [2])
union([1, 2], [2, 3])
flatten([1, [2, [3, [4]]]])
Function reference
Each function with its examples and edge cases. The heading links to the function's own page with its parameter table.
list contains
list contains(list, element)
Returns true if the list contains the element. Unlike the = operator, it can also test for null.
The element may be null, so list contains also tests whether a list has a null entry. Comparison is by value with no type conversion.
list contains([1, 2, 3], 2)
list contains([1, null, 3], null)
list contains([1.0, 2], 1)
list contains([date("2026-01-01")], date("2026-01-01"))
list contains([], 1)
count
count(list)
Returns the number of elements in the list.
count([1, 2, 3])
count([])
min
min(list) or min(c1, …, cN)
Returns the smallest element. All elements must be comparable with each other (numbers, strings, or temporal values).
min([1, 2, 3])
min("a", "b", "c")
min([])
max
max(list) or max(c1, …, cN)
Returns the largest element. All elements must be comparable with each other.
max(1, 2, 3)
max([date("2026-01-01"), date("2026-07-24")])
max([1, null, 3][item != null])
sum
sum(list) or sum(n1, …, nN)
Returns the sum of the numbers. The sum of an empty list is null.
sum takes either one list or several numbers as separate arguments. The two things that surprise people are that an empty list sums to null, not 0, and that one null element makes the whole sum null. Both matter when the list comes from a filter that can match nothing.
To sum a field across a list of contexts, select the field: sum(orders.amount). To sum a computed value, use for.
sum([1, 2, 3])
sum([])
sum([1, 2][item > 5])
A filter that matches nothing gives an empty list, and its sum is null, not 0. B-FEEL returns 0.
sum([1, null, 3])
sum([1, null, 3][item != null])
sum([0.1, 0.2])
FEEL numbers are decimal, so there is no floating-point rounding error.
sum(for o in [{price: 2, qty: 3}, {price: 5, qty: 1}] return o.price * o.qty)
sum([duration("PT1H"), duration("PT30M")])
sum only adds numbers; durations give null.
mean
mean(list) or mean(n1, …, nN)
Returns the arithmetic average of the numbers; null for an empty list.
mean([1, 2, 3])
mean([])
median
median(list) or median(n1, …, nN)
Returns the median: the middle element of the sorted values, or the mean of the two middle elements for an even count.
median(8, 2, 5, 3, 4)
median([6, 1, 2, 3])
median([])
stddev
stddev(list) or stddev(n1, …, nN)
Returns the sample standard deviation of the numbers.
stddev(2, 4, 7, 5)
mode
mode(list) or mode(n1, …, nN)
Returns the most frequent value(s) as a list; ties produce several results in ascending order.
mode(6, 3, 9, 6, 6)
mode([6, 1, 9, 6, 1])
all
all(list) or all(b1, …, bN)
Returns true if every element is true, false if any element is false, and null otherwise. all([]) is true.
all uses three-valued logic. A single false makes the result false, even if there are nulls. Otherwise any null makes it null. Elements that are not booleans also give null.
all([true, true])
all([true, false])
all([])
all([true, null])
any
any(list) or any(b1, …, bN)
Returns true if at least one element is true, false if all are false, and null otherwise. any([]) is false.
any([false, true])
any([])
any([null, false])
sublist
sublist(list, start position, length?)
Returns the slice of the list starting at start position, running to the end or for length elements.
sublist([4, 5, 6], 1, 2)
sublist([4, 5, 6], -1)
append
append(list, item…)
Returns a new list with the items added to the end.
append([1], 2, 3)
append([1], [2])
A list argument is added as one nested element. Use concatenate to join lists.
concatenate
concatenate(list…)
Returns one list containing the elements of all argument lists, in order.
concatenate([1, 2], [3])
concatenate([1], [2], [3])
insert before
insert before(list, position, newItem)
Returns a new list with newItem inserted before the given position.
insert before([1, 3], 1, 2)
insert before([1, 2], 3, 9)
The position must exist, so this cannot append. Use append.
remove
remove(list, position)
Returns a new list with the element at the given position removed.
remove([1, 2, 3], 2)
remove([1, 2, 3], 5)
reverse
reverse(list)
Returns the list in reverse order.
reverse([1, 2, 3])
index of
index of(list, match)
Returns the positions of all occurrences of match, as an ascending list of 1-based indexes.
index of([1, 2, 3, 2], 2)
union
union(list…)
Returns all elements of the argument lists with duplicates removed, preserving first-seen order.
union([1, 2], [2, 3])
distinct values
distinct values(list)
Returns the list with duplicate elements removed, preserving first-seen order.
distinct values([1, 2, 3, 2, 1])
duplicate values
duplicate values(list)
Returns the values that appear more than once in the list.
duplicate values([1, 2, 3, 2, 1])
flatten
flatten(list)
Returns a flat list with all nested lists recursively expanded in place.
flatten([[1, 2], [[3]], 4])
product
product(list) or product(n1, …, nN)
Returns the product of the numbers.
product(2, 3, 4)
product([])
product([2, null])
sort
sort(list, precedes)
Returns the list sorted by the precedes function.
The precedes function decides the order: it receives two elements and returns true if the first belongs before the second. To sort contexts, compare the field you want. To sort in descending order, use >.
DMN 1.6 lists both parameters without marking precedes optional. The engine behind this site also accepts sort(list) for comparable elements and sorts them ascending, but a portable model passes the function.
sort([3, 1, 2], function(x, y) x < y)
sort(["b", "a", "c"], function(x, y) x < y)
sort([{n: "b"}, {n: "a"}], function(x, y) x.n < y.n)
Sort contexts by a field.
list replace
list replace(list, position | match, newItem)
Returns a new list with the element at the position, or every element accepted by the matcher function, replaced by newItem.
list replace([2, 4, 7, 8], 3, 6)
list replace([2, 4, 7, 8], function(item, newItem) item > 5, 0)
partition
partition(list, size)
Not part of the DMN 1.6 standard: an extension supported by the engine behind this site. A model that uses it may not run on other DMN engines.
Splits the list into consecutive chunks of the given size; the last chunk may be shorter.
partition([1, 2, 3, 4, 5], 2)
How B-FEEL differs
In standard FEEL an invalid argument makes the result null. The business-friendly
B-FEEL dialect returns a type default instead. Both columns were evaluated by the same engine:
| Expression | FEEL | B-FEEL |
|---|---|---|
| sum([1, "2", 3]) | null | 4 |
| index of(null, 1) | null | [] |
| sublist(null, 1) | null | [] |
More FEEL guides
FEEL string functions · FEEL numeric functions · FEEL date and time functions · Language constructs · Examples cheat sheet
Defined by the OMG DMN 1.6 specification, chapter 10.3.4 (built-in functions).