mirror of
https://github.com/Jermolene/TiddlyWiki5
synced 2024-12-24 00:50:28 +00:00
Add "reduce" and "filter" operators
This commit is contained in:
parent
0027b990e4
commit
14a28b7779
31
core/modules/filters/filter.js
Normal file
31
core/modules/filters/filter.js
Normal file
@ -0,0 +1,31 @@
|
||||
/*\
|
||||
title: $:/core/modules/filters/filter.js
|
||||
type: application/javascript
|
||||
module-type: filteroperator
|
||||
|
||||
Filter operator returning those input titles that pass a subfilter
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
/*
|
||||
Export our filter function
|
||||
*/
|
||||
exports.filter = function(source,operator,options) {
|
||||
var filterFn = options.wiki.compileFilter(operator.operand),
|
||||
results = [],
|
||||
target = operator.prefix !== "!";
|
||||
source(function(tiddler,title) {
|
||||
var list = filterFn.call(options.wiki,options.wiki.makeTiddlerIterator([title]));
|
||||
if((list.length > 0) === target) {
|
||||
results.push(title);
|
||||
}
|
||||
});
|
||||
return results;
|
||||
};
|
||||
|
||||
})();
|
54
core/modules/filters/reduce.js
Normal file
54
core/modules/filters/reduce.js
Normal file
@ -0,0 +1,54 @@
|
||||
/*\
|
||||
title: $:/core/modules/filters/reduce.js
|
||||
type: application/javascript
|
||||
module-type: filteroperator
|
||||
|
||||
Filter operator evaluats a subfilter for each item, making the running total available in the variable `accumulator`, and the current index available in the variable `index`
|
||||
|
||||
\*/
|
||||
(function(){
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
/*
|
||||
Export our filter function
|
||||
*/
|
||||
exports.reduce = function(source,operator,options) {
|
||||
// Accumulate the list
|
||||
var results = [];
|
||||
source(function(tiddler,title) {
|
||||
results.push(title);
|
||||
});
|
||||
// Run the filter over each item
|
||||
var filterFn = options.wiki.compileFilter(operator.operand),
|
||||
accumulator = operator.suffix || "";
|
||||
for(var index=0; index<results.length; index++) {
|
||||
var title = results[index],
|
||||
list = filterFn.call(options.wiki,options.wiki.makeTiddlerIterator([title]),{
|
||||
getVariable: function(name) {
|
||||
switch(name) {
|
||||
case "currentTiddler":
|
||||
return "" + title;
|
||||
case "accumulator":
|
||||
return "" + accumulator;
|
||||
case "index":
|
||||
return "" + index;
|
||||
case "revIndex":
|
||||
return "" + (results.length - 1 - index);
|
||||
case "length":
|
||||
return "" + results.length;
|
||||
default:
|
||||
return options.widget.getVariable(name);
|
||||
}
|
||||
}
|
||||
});
|
||||
if(list.length > 0) {
|
||||
accumulator = "" + list[0];
|
||||
}
|
||||
}
|
||||
return [accumulator];
|
||||
};
|
||||
|
||||
})();
|
9
editions/tw5.com/tiddlers/filters/examples/Brownies.tid
Normal file
9
editions/tw5.com/tiddlers/filters/examples/Brownies.tid
Normal file
@ -0,0 +1,9 @@
|
||||
created: 20201004145650743
|
||||
modified: 20201006181234412
|
||||
price: 4.99
|
||||
quantity: 1
|
||||
tags: shopping
|
||||
title: Brownies
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
//This is a sample shopping list item for the [[Shopping List Example]]//
|
@ -0,0 +1,9 @@
|
||||
created: 20201004145612358
|
||||
modified: 20201006181232439
|
||||
price: 1.32
|
||||
quantity: 5
|
||||
tags: shopping
|
||||
title: Chick Peas
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
//This is a sample shopping list item for the [[Shopping List Example]]//
|
9
editions/tw5.com/tiddlers/filters/examples/Milk.tid
Normal file
9
editions/tw5.com/tiddlers/filters/examples/Milk.tid
Normal file
@ -0,0 +1,9 @@
|
||||
created: 20201004145636906
|
||||
modified: 20201006181233518
|
||||
price: 0.46
|
||||
quantity: 12
|
||||
tags: shopping
|
||||
title: Milk
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
//This is a sample shopping list item for the [[Shopping List Example]]//
|
@ -0,0 +1,9 @@
|
||||
created: 20201004145502135
|
||||
modified: 20201006181230956
|
||||
price: 2.66
|
||||
quantity: 4
|
||||
tags: shopping
|
||||
title: Rice Pudding
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
//This is a sample shopping list item for the [[Shopping List Example]]//
|
@ -0,0 +1,23 @@
|
||||
created: 20201004141030951
|
||||
modified: 20201004143326056
|
||||
tags: [[Operator Examples]] [[filter Operator]]
|
||||
title: filter Operator (Examples)
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
\define larger-than-1k() [get[text]length[]compare:integer:gteq[1000]]
|
||||
\define smaller-than-2k() [get[text]length[]compare:integer:lteq[2000]]
|
||||
\define contains-missing-links() [links[]!is[shadow]is[missing]]
|
||||
\define display-variable(name)
|
||||
''<$text text=<<__name__>>/>'': <code><$text text={{{ [<__name__>getvariable[]] }}}/></code>
|
||||
\end
|
||||
|
||||
These examples use the following predefined variables:
|
||||
|
||||
* <<display-variable larger-than-1k>>
|
||||
* <<display-variable smaller-than-2k>>
|
||||
* <<display-variable contains-missing-links>>
|
||||
|
||||
<<.operator-example 1 "[tag[HelloThere]filter<larger-than-1k>]">>
|
||||
<<.operator-example 2 "[tag[HelloThere]filter<smaller-than-2k>]">>
|
||||
<<.operator-example 3 "[tag[HelloThere]filter<larger-than-1k>filter<smaller-than-2k>]">>
|
||||
<<.operator-example 4 "[tag[Features]filter<contains-missing-links>]">>
|
@ -1,16 +1,34 @@
|
||||
created: 20201004154413968
|
||||
modified: 20201004154413968
|
||||
modified: 20201006181831622
|
||||
tags: [[Operator Examples]] [[reduce Operator]]
|
||||
title: reduce Operator (Examples)
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
\define add-numbers() [get[text]length[]compare:integer:gteq[1000]]
|
||||
\define add-price() [get[price]multiply{!!quantity}add<accumulator>]
|
||||
\define num-items() [get[quantity]add<accumulator>]
|
||||
\define display-variable(name)
|
||||
''<$text text=<<__name__>>/>'': <code><$text text={{{ [<__name__>getvariable[]] }}}/></code>
|
||||
\end
|
||||
|
||||
These examples use the following predefined variables:
|
||||
|
||||
* <<display-variable add-numbers>>
|
||||
* <<display-variable add-price>>
|
||||
* <<display-variable num-items>>
|
||||
|
||||
<<.operator-example 1 "[tag[HelloThere]filter<larger-than-1k>]">>
|
||||
They also use the following data tiddlers:
|
||||
|
||||
<ul>
|
||||
<$list filter="[tag[shopping]!has[draft.of]]">
|
||||
<li>
|
||||
''<$link><$text text=<<currentTiddler>>/></$link>'' quantity: <$text text={{!!quantity}}/>, price: <$text text={{!!price}}/>
|
||||
</li>
|
||||
</$list>
|
||||
</ul>
|
||||
|
||||
Number of items:
|
||||
|
||||
<<.operator-example 1 "[tag[shopping]reduce<num-items>]">>
|
||||
|
||||
Total price:
|
||||
|
||||
<<.operator-example 2 "[tag[shopping]reduce<add-price>]">>
|
||||
|
33
editions/tw5.com/tiddlers/filters/filter.tid
Normal file
33
editions/tw5.com/tiddlers/filters/filter.tid
Normal file
@ -0,0 +1,33 @@
|
||||
caption: filter
|
||||
created: 20200929174420821
|
||||
modified: 20201006173606828
|
||||
op-input: a [[selection of titles|Title Selection]] passed as input to the filter
|
||||
op-neg-input: a [[selection of titles|Title Selection]] passed as input to the filter
|
||||
op-neg-output: those input titles that <<.em "do not">> pass the filter <<.place S>>
|
||||
op-output: the [[selection of titles|Title Selection]] that pass the filter <<.place S>>
|
||||
op-parameter: a [[filter expression|Filter Expression]]
|
||||
op-parameter-name: S
|
||||
op-purpose: apply a subfilter to each input title and return the titles that return a non-empty result from the subfilter
|
||||
tags: [[Filter Operators]] [[Negatable Operators]]
|
||||
title: filter Operator
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
<<.from-version "5.1.23">> The <<.op filter>> operator runs a subfilter for each input title, and returns those input titles for which the subfilter returns a non-empty result (in other words the result is not an empty list). The results of the subfilter are thrown away.
|
||||
|
||||
Simple filter operations can be concatenated together directly (eg `[tag[HelloThere]search[po]]`) but this doesn't work when the filtering operations require intermediate results to be computed. The <<.op filter>> operator can be used to filter on an intermediate result which is discarded. To take the same example but to also filter by those tiddlers whose text field is longer than 1000 characters:
|
||||
|
||||
```
|
||||
<$vars myfilter="[get[text]length[]compare:integer:gteq[1000]]">
|
||||
<$list filter="[tag[HelloThere]search[po]filter<myfilter>]">
|
||||
<div>
|
||||
<$link>
|
||||
<$text text=<<currentTiddler>>/>
|
||||
</$link>
|
||||
</div>
|
||||
</$list>
|
||||
</$vars>
|
||||
```
|
||||
|
||||
<<.tip "Compare with the similar [[subfilter|subfilter Operator]] operator which runs a subfilter and directly returns the results">>
|
||||
|
||||
<<.operator-examples "filter">>
|
27
editions/tw5.com/tiddlers/filters/reduce.tid
Normal file
27
editions/tw5.com/tiddlers/filters/reduce.tid
Normal file
@ -0,0 +1,27 @@
|
||||
caption: reduce
|
||||
created: 20201004154131193
|
||||
modified: 20201006174749170
|
||||
op-input: a [[selection of titles|Title Selection]] passed as input to the filter
|
||||
op-output: the final result of running the subfilter <<.place S>>
|
||||
op-parameter: a [[filter expression|Filter Expression]]
|
||||
op-parameter-name: S
|
||||
op-purpose: apply a subfilter to each input title in turn, accumulating a single value
|
||||
op-suffix: Initial value for accumulator
|
||||
op-suffix-name: V
|
||||
tags: [[Filter Operators]]
|
||||
title: reduce Operator
|
||||
type: text/vnd.tiddlywiki
|
||||
|
||||
<<.from-version "5.1.23">> The <<.op reduce>> operator runs a subfilter for each input title, passing the result of the previous subfilter run as a variable. The initial value of the accumulator can optionally be specified. It returns the result of the final subfilter run.
|
||||
|
||||
The <<.op reduce>> operator is used to flatten a list of items down to a single item by repeatedly applying a formula. A typical use is to add up the values in a given field of a list of tiddlers.
|
||||
|
||||
The following variables are available within the subfilter:
|
||||
|
||||
* ''accumulator'' - the result of the previous subfilter run
|
||||
* ''currentTiddler'' - the input title
|
||||
* ''index'' - the numeric index of the current list item (with zero being the first item in the list)
|
||||
* ''revIndex'' - the reverse numeric index of the current list item (with zero being the last item in the list)
|
||||
* ''length'' - the total length of the input list
|
||||
|
||||
<<.operator-examples "reduce">>
|
@ -22,4 +22,6 @@ type: text/vnd.tiddlywiki
|
||||
...
|
||||
```
|
||||
|
||||
<<.tip "Compare with the similar [[filter|filter Operator]] operator which runs a subfilter against each title, returning those titles that return a non-empty list (and discards the results of the subfilter)">>
|
||||
|
||||
<<.operator-examples "subfilter">>
|
||||
|
Loading…
Reference in New Issue
Block a user