Skip to main content
All CollectionsBasic features & How to
Advanced Filter In-Depth Guide
Advanced Filter In-Depth Guide
Mark avatar
Written by Mark
Updated over 7 months ago

This detailed guide was submitted by one of our amazing users! Thanks so much to Keith Edmunds.

The Marvin Advanced Filter

The Advanced Filter in Marvin is very powerful, but it is also one of the more complex areas of the application.

This page aims to explain how to use the Advanced Filter step by step, and to explain a little of how it works.

Terminology

Before we get into the details, we need to define a few terms. Consider this simple maths expression:

2 + 1 = 3

Here the + sign is called an operator, and the 2 and 1 are called operands. Operands are the data in an expression, and operators tell us how to combine that data to get a result.

We learned in school that parentheses - another operator - are used to define priority:

3 ✕ 2 + 1 = 7
3 ✕ (2 + 1) = 9

In the first expression above, we calculate the 3 ✕ 2 part first because the multiplication operator has a higher precedence.

If it were written 1 + 2 ✕ 3, the answer would still be 7 because the multiplication operator has a higher precedence than the addition operator, and thus the multiplication part of the expression must be calculated first.

In the second expression, we calculate the 2 + 1 part first because the parentheses have a higher precedence than the multiplication operator and thus the part of the expression inside the parentheses must be calculated first.

Reverse Polish Notation

Marvin’s Advanced Filter uses something called Reverse Polish Notation (RPN). This differs from the more usual way of writing expressions in two key ways:

  • it doesn't use parentheses to manage precedence; and

  • the operators appear after the operands rather than before or between them

If we rewrite 3 ✕ 2 + 1 using RPN, we get:

3 2 ✕ 1 +

There is a simple process to interpret RPN which is as follows:

  • scan the expression from left to right and stop at the first operator

  • step back (to the left) to find the operand(s) to use

  • replace the operands and operator with the result

  • repeat the process until the expression is fully evaluated

Let's try that on our 3 2 ✕ 1 + expression.

First we scan the expression from left to right and stop at the first operator, so we pass the 3 and 2 and stop at the first operator which is the .

Next we step back (to the left) to find the operands to use. The multiplication operator needs two operands, so we back off to the left and find the 3 and 2.

Now we replace the operands and operator with the result, so we replace the 3 2 ✕ with the result, 6, to give:

6 1 +

Finally, we repeat the process until the expression is fully evaluated. We scan the expression from left to right and stop at the first operator, which is now the +.

We step back (to the left) to find the operands to use. The + needs two operands, so we find 6 and 1.

We replace the operands and the operator with the result, so we replace the 6 1 + with 7.

The expression is now fully evaluated so we are finished.

Converting expressions to RPN

We can convert non-RPN expressions to RPN using a similar process:

  • scan the expression and find the highest precedence operator

  • find the operands and write them down followed by the operator

  • remove those operands and operator from the original expression

  • repeat the process until the expression is fully evaluated

Let's use the same example, 3 ✕ 2 + 1, step by step.

First we scan the expression and find the highest precedence operator, which is the multiplication operator.

Then we find the operands and write them down followed by the operator. The operands are the 3 and the 2, so we write down:

3 2 ✕

Next we remove those operands and operators from the original expression which leaves us with

+ 1

Finally we repeat the process by scanning the expression and find the highest precedence operator which is the +.

We find the operands and write them down followed by the operator. The operand is the 1, so we put 1 + on the end of what we already have, giving:

3 2 ✕ 1 +

Removing those operands and operators from the original expression leaves nothing, so we're complete.

What about parentheses?

Earlier we looked at the expression:

3 ✕ (2 + 1) = 9

We can use the same rules to convert that expression to RPN. First, we scan the expression and find the highest precedence operator.

This time the parentheses have the highest precedence. We don't use parentheses in RPN; instead, we simply process the contents of the parentheses as the highest precedence. So, because of the parentheses, the + operator is processed first.

Now find the operands and write down the operands followed by the operator. The + sign's operands are 2 and 1, so we write down

2 1 +

Removing those operands and operators from the original expression leaves us with

3 ✕

Now we repeat the process by scanning the expression to find the highest precedence operator which is the .

Next, find the operands and write down the operands followed by the operator to give:

2 1 + 3 ✕

Remove those operands and operators from the original expression, and we have finished.

How does this apply to Marvin?

All of the examples and discussion above used simple maths expressions because they are generally easy to understand.

Marvin, of course, is not calculating an answer. Instead it is filtering from all of our tasks to show only the ones we want.

Before we look at the filtering itself, we need to understand some of the operators that Marvin uses. They're all listed on the Advanced Filter help page, but the ones we'll use are shown below. We’ll highlight the Marvin operators and operands in gray to differentiate them from the other text.

  • || meaning "or" (note this is two bar characters, not uppercase i or lowercase L characters).

  • && meaning "and"

  • ! meaning "not". This is an unusual operator in that it takes only one operand.

We'll use those operators in the following examples.

We'll assume that we have Marvin set up with the following categories and labels:

  • three categories of tasks: #home, #work and #hobby

  • one label: @quick

We also have the three standard priorities known in the Advanced Filter as *"red star" (high), *"orange star" (medium) and *"yellow star" (low).

Example: list high priority work tasks

We can express this as "all tasks that are in the category ‘work’ AND which have a high priority".

#work will match all work tasks. *"red star" will match all high priority tasks. To match tasks that are both, we need the AND operator, &&. As before, we write down the operands followed by the operator:

#work *"red star" &&

Example: list all quick tasks that are in the home or work category

We want tasks that are: @quick AND (#home OR #work)

The highest precedence is the part in parentheses, (#home or #work), which becomes:

#home #work ||

That leaves us @quick AND which gives us:

#home #work || @quick &&

Example: list quick tasks that are not in the hobby category

We want tasks that are: @quick AND NOT #hobby

NOT is an operator, represented by !, that takes a single operand, and it has the highest precedence. Again, we write down the operands (just one in this case) followed by the operator:

#hobby !

That leaves @quick AND, which we process in the same way giving the final result of:

#hobby ! @quick &&

Example: list all quick tasks, but omit those that are in the hobby category unless they are high priority

This is a little more complicated. If we define what we want in a non-RPN way using parentheses, we want tasks that are: (@quick and not #hobby) or (@quick and #hobby and high priority)

Be careful how you express requirements like this. It would very easy to use natural English and say we want tasks that are "(@quick and not #hobby)" and tasks that are "(@quick and #hobby and high priority)", but that’s misleading.

We want tasks that are in one group OR the other. If we use "and", we'll get no tasks (no task is simultaneously in and not in the #hobby category).

The "(@quick and not #hobby)" part is exactly the same as the last example, so we can use that as a partial result and remove that part from the remaining expression to give:

partial result: #hobby ! @quick &&

remaining expression: or (@quick and #hobby and high priority)

The part inside the parentheses has the highest precedence, and each part within them has equal precedence, so we can reduce "@quick and #hobby" to @quick #hobby &&.

If we add that to our partial result and remove it from the original expression, we get:

partial result: #hobby ! @quick && @quick #hobby &&

remaining expression: or (and high priority)

The remaining part within the parentheses has the highest precedence and becomes *"red star” &&. That just leaves 'or' as the original expression:

partial result: #hobby ! @quick && @quick #hobby && *"red star" &&

remaining expression: or

We simply add the ‘or’ to the partial result to give the final result:

#hobby ! @quick && @quick #hobby && *"red star" && ||

That looks complicated, but we can check that by decoding it using our rules from earlier. First we scan the RPN expression from left to right and stop at the first operator, which is !.

Then we step back (to the left) to find the operand(s) to use. We only need one operator for ! and that's #hobby.

We replace the operands and operator with the result. For clarity here, we’ll highlight our replacement in bold to make it easy to see. Remember, those highlighted parts we treat as one operand. We now have:

not #hobby @quick && @quick #hobby && *"red star" && ||

Now we repeat the process, so we scan the remaining expression from left to right and stop at the first operator which is &&.

Then we step back (to the left) to find the operand(s) to use, which are not #hobby and @quick. That gives us:

not #hobby and @quick @quick #hobby && *"red star" && ||

Starting again, the first operator is &&, the two operands before it are @quick and #hobby, so we now have:

not #hobby and @quick @quick and #hobby *"red star" && ||

Notice that the two bold parts are not connected. The && operator we just processed only consumed the @quick and #hobby operands and didn’t affect the existing bold part.

Now the first operator is &&, the two operands before it are *"red star" and @quick and #hobby, so we now have:

not #hobby and @quick @quick and #hobby and *"red star" ||

The first and only remaining operator is ||, and that joins the only two operands, not #hobby and @quick and @quick and #hobby and *"red star", to give:

not #hobby and @quick OR @quick and #hobby and *"red star"

That brings us back where we started.

Incidentally, we didn’t need to specify #hobby in the second part of the RPN. We could have simply written:

#hobby ! @quick && @quick *"red star" && ||

Can you see why that would give the same result?

Example: all planned tasks for this week, all tasks which are unplanned, and all tasks scheduled for the coming seven days

Again we need to be careful of the "and" in that description. We can express this as:

(planned for this week) or (unplanned) or (scheduled in next 7 days)

The first operator is "or". Looking on the Advanced Filter help page we can see that "Planned for this week" is simply @thisWeek, and "unplanned" is &unplanned. Combining those with || give us:

partial result: &thisWeek &unplanned ||

remaining expression: or (scheduled in next 7 days)

We can specify a scheduled date with the operand scheduleDate and a time, in this case 7d. The operator that joins them is <=, meaning "less than or equal".

So, scheduleDate 7d <= matches all tasks scheduled some time in the next seven days. Taking the "or" into account as well gives us:

&thisWeek &unplanned || *scheduleDate 7d <= ||

Conclusion

The Amazing Marvin Advanced Filter is powerful, but it's fair to say that some experience is needed to get the best from it. The starting point is the Help page, but if you still have problems then the Amazing Marvin Facebook group is a good source of support.

Did this answer your question?