How do I filter for the intersection of sets?

239 views
Skip to first unread message

c pa

unread,
Jun 25, 2015, 7:35:43 PM6/25/15
to tiddl...@googlegroups.com
The documentation for Filter Expression states the following:

If a run has a + prefix, it receives the filter's output so far as its input. The filter's output is then completely replaced by the run's output. Any subsequent run reverts to receiving all tiddler titles as its input, unless it too has a + prefix.

But then it states:

Run     Interpretation     Output
run     union of sets     ... OR run
+run     intersection of sets     ... AND run
-run     difference of sets     ... AND NOT run

What I want is the second behavior I want tiddlers from run 1 that are also in run 2. What I'm getting is just run2 regardless of what I put in run1. That doesn't seem to be useful.

Jed Carty

unread,
Jun 25, 2015, 9:13:09 PM6/25/15
to tiddl...@googlegroups.com
Can you post an example? It sounds like you are using a selection constructor (http://tiddlywiki.com/#Selection%20Constructors) in your second run. I am getting the expected behavior on tiddlywiki.com, the code

<$list filter='[tag[HelloThere]]+[tag[Learning]]'>

</$list>

Gives an empty list and

<$list filter='[tag[Concepts]]+[tag[Filters]]'>

</$list>

Just gives 'Filter Operators'.

c pa

unread,
Jun 25, 2015, 10:48:21 PM6/25/15
to tiddl...@googlegroups.com
Yes. I have an example here: http://cpashow.tiddlyspot.com/#Filter%20Intersection

here's the code:

tags: jack kill tom
authors: tom dick harry

<u>in authors but not tags</u>
<$list filter="[list[!!authors]] -[all[current]tags[]]">
    <li>{{!!title}}</li>
</$list>
<u>in authors and tags</u>
<$list filter="[list[!!authors]] +[all[current]tags[]]">
    <li>{{!!title}}</li>
</$list>

Jed Carty

unread,
Jun 26, 2015, 2:00:22 AM6/26/15
to tiddl...@googlegroups.com
As far as I can tell this is an order of operations thing. Both list and tags replace the current list instead of applying a filter to it. It looks like the second one (the one that isn't working) is applying each thing in turn from left to right while the first one is evaluating the expression separately before taking the set difference. In cases where you aren't using a selection constructor there isn't a difference between applying each one sequentially and evaluating them separately before taking the intersection.

So the first statement is correct, the part about set intersections doesn't hold for all operators. It is a convenient shorthand, but we may want to update the documentation.

So, with those problems one way you can get the behavior you want would be like this:

<$list filter='[list[!!authors]]' variable=ThisAuthor>
<$list filter='[all[current]tags[]]+[field:title<ThisAuthor>]'>

</$list>
</$list>

it is certainly not ideal, but it works for your example at least. More complex things may cause trouble.

c pa

unread,
Jun 26, 2015, 11:05:04 AM6/26/15
to tiddl...@googlegroups.com
For simple lists that works. I needed a more robust solution and solved the problem with the following code: -simplified

\define displayAuthor(tiddlerName)
    <!-- This macro (for demo purposes) displays the author's name in a list. You can use the variable tiddlerName for any purpose -->
    <li>$tiddlerName$</li>
\end
\define runMacroOnFilterIntersection(filter1, filter2, macroName)
    <!-- This macro runs a passed macro once per value that exists in both filter1 and filter2 -->
    <$list filter="$filter1$" variable="filter1">
        <!-- Now that we have one item from filter1 (in the variable filter1), lets compare it to filter2 -->
        <$list filter="$filter2$" variable="filter2">
            <!-- We now have the first item in filter2 (In the variable filter2) run the macro only if the two values filter1 == filter2 -->
            <$reveal default=<<filter1>> type="match" text=<<filter2>> >
                $macroName$
            </$reveal>
        </$list>
    </$list>
\end

<!-- Example of a set of complex filter calls. In the filter you must use [field:title[ because a passed [[ gets parsed -->
<$macrocall $name="runMacroOnFilterIntersection"
            filter2="[list[!!authors]]"
            filter1="[field:title[$:/data/authors]indexes[]removeprefix[alt:]]"
            macroName="<$macrocall $name='displayAuthor' tiddlerName=<<filter2>> />"
/>

Majid al-Dosari

unread,
May 7, 2016, 10:50:07 AM5/7/16
to TiddlyWiki
excellent!

seriously the doc is confusing. there is a difference b/w intersection in the mathematical sense and the way things are described in the docs.
Reply all
Reply to author
Forward
0 new messages