Got rid of recursion using the reduce operator

This really flashed me, so I thought I might just share it.

Here’s the scoop: I have some data stored in several fairly complex (i.e. doubly-nested) JSON data tiddlers. About two years ago I wrote a routine to display these tiddlers in a tabular way. At the time I used Josh Fontanay’s JSONMangler plugin which (I think) since version 5.2.1 is no longer compatible with TW. The new JSON operators introduced with 5.2.4 got me have another look at this, and I was able to significantly ease up the code using these and the new :filter filter run prefix (see this thread: Accessing JSON data tiddlers - Discussion - Talk TW (tiddlywiki.org).

A major annoyance, when I orginally wrote the code was that I needed to calculate rowspans based on the number of items in the JSON data, since TW doesn’t really shine when it comes to manipulating variables in Wikitext. Someone from the community helped me to solve this using recursion. It worked, but I always hated it b/c the code was ugly and not really maintainable.

Out of a whim I thought, maybe the reduce[] operator could do the trick and - you’ve already guessed it - it does. And the code is so much more elegant. Here we go:

<!-- 
json: data tiddler JSON content retrieved from data tiddlers somewhere else via get[text] 
Array1: array of objects
Array2: array of objects within Array1
-->

<!-- sumUp: worker function passed as a parameter to reduce[] Note usage of <index> for accessing the individual items of Array1 and <accumulator> for adding up the values -->
\define sumUp() [<json>jsonindexes[Array1],<index>,[Array2]count[]add<accumulator>]

\define makeRowspan()
	<!-- renders a number based on the total number of items as defined by the total number of items of the various instances of Array2 -->

	<$list variable="itemCount" filter="[<json>jsonindexes[Array1]reduce<sumUp>]">
		<<itemCount>>
	</$list>
\end

<!-- somewhere in main routine where the table needs to be drawn -->

<!-- Haven't yet figured out a way to get around wikify. Otherwise makeRowspan is inserted literally  -->
<$wikify name="rows" text=<<makeRowspan>> >
	<td rowspan=<<rows>> > 
		<!-- table content goes here -->
	</td>
</$wikify>

This made my day. Thought I share it, as concepts like reduce[] might seem somewhat arkane to the occasional coder (i.e. people like me), but can get really useful once you get your head wrapped around it (QED). Now, as stated above, I only need to get rid of wikifiy…

1 Like

Try something along these lines:


<td rowspan={{{ [<json>jsonindexes[Array1]] :reduce[<json>jsonindexes[Array1],<index>,[Array2]count[]add<accumulator>] }}}>

    <!-- table content goes here -->

</td>
2 Likes

Works. Marvelous. Didn’t realize it would be that easy. Thanks so much

1 Like