Help with a complex filter needed

Hi all,

What I want to achieve is a “colspan” Map for TiddlyWiki tables in wikitext
I want to create a “rowspan” Map in a similar manner but let’s start with the colspan Map since that appears to be easier

I start with a TiddlyWiki table and put it in a variable wikitextTable:

|Cell1 |Cell2 |Cell3 |Cell4 |
|Cell5 |Cell6 |Cell7 |<|
|Cell5 |~|Cell7 |Cell8 |
|>|>|Cell10 |Cell11 |

I get the single rows:

[<wikitextTable>!is[blank]splitregexp[\n]!suffix[|h]!suffix[|c]!suffix[|f]!suffix[|k]]

I get the single cells:

[<wikitextRows>!is[blank]splitregexp[\|]]

Now I want to iterate over the single cells and create a map in the following style for the last row for example:

0 0 3 1

It can get more complex when the last row looks like this:

|>|>|Cell10 |<|

and the output should be

0 0 4 0

but it could also be “invalid”

|>|>|<|Cell11 |

also this would be

0 0 3 1

Does anybody have an idea how to create that filter?
Would be absolutely appreciated!

Thanks in advance,
Simon

Its not clear to me where the 3 and 1 map values come from. I assume they relate to the intended size (or order?) of those columns.

Nonetheless, something to remember when working with your “map” lists: since they can contain multiple items with the same value, you will probably want to use enlist:raw[...] when handling those map lists, so that the duplicate map values will be preserved rather than collapsed into single values by the default “dominant append” filter handling.

-e

Hi @EricShulman , thanks for replying

0 means it spans no cell (I need that value)
1 spans only one cell (standard)
2 spans two cells
3 spans three cells
4 spans 4 cells

Hi @BurningTreeC

I was wondering how @Charlie_Veniot would solve this one, and I think he would search-replace using unicode characters, so here’s a try at it:

  • Take your row (as a string)
  • Replace every || by |x|
  • Remove first and last | and split by |
  • Replace every cell value not matching > or < by a 1 (with a regexp)
  • Replace every > by a :arrow_right:
  • Replace every < by a :arrow_left:
  • Join values without separator
  • Find substrings matching regexp ➡️*1⬅️* and replace the 1 by the substring length
  • Replace every :arrow_right: or :arrow_left: by a 0
  • Split each char, join with space

Hope this helps,

Fred

Argh, it will only work if collapsed cells are <10… :frowning_face:

Hi @tw-FRed and thank you!
I took inspiration from you!

\function tf.get.colspan.map() [<wikitextTable>!is[blank]splitregexp[\n]!suffix[|h]!suffix[|c]!suffix[|f]!suffix[|k]nth<rowIndex>splitregexp[\|]!match[]] :map[!match[>]!match[<]then[1]else<currentTiddler>] :map[match[>]then[0]else<currentTiddler>] :map[match[<]then[x]else<currentTiddler>] +[join[ ]]

\function tf.get.rowspan.map() [<wikitextTable>!is[blank]splitregexp[\n]!suffix[|h]!suffix[|c]!suffix[|f]!suffix[|k]splitregexp[\|]!match[]] :filter[<index>remainder<columns>match<previousColIndex>] :map[!match[~]then[1]else[0]] +[join[ ]]

Like this I get a “map” of the form:

1 1 0 1 0 1 1 x

where 0 stands for > and x stands for < (I could also let that one be <)


I try doing this in two steps.
Now I’d need a filter that accumulates consecutive or single 0, adds them to the next 1 as amount of consecutive 0 + 1 and replaces those 0 with a marker, say _ (so that later on I can use the produced list to get indexes correctly)

In a similar way and in a second step, I think I’d need to reverse the produced list and look for consecutive or single x and do the same as before…

Any idea appreciated :slightly_smiling_face:

Yours is a precarious tip-toe across the mined and barb-wired landscape that is my sponge. Maybe not the safest place to travel.

(aside: your arrow emojis are semantically oh-so-much better; I only looked at your code after I finished mine.)

My snippet of code to explore:

<$let wikitextTable="""|Cell1 |Cell2 |Cell3 |Cell4 |
|Cell5 |Cell6 |Cell7 |<|
|Cell5 |~|Cell7 |Cell8 |
|>|>|Cell10 |Cell11 |
|>|>|Cell10 |<|
|>|>|<|Cell11 |""">

<$list variable="row" filter="[<wikitextTable>splitregexp[\n]]"> 
<hr style="border:1px solid red">
row: <<row>>
<hr style="border:1px solid red">
(
<$list variable="cell" filter="[<row>search-replace:g[>|],[🟦]search-replace:g[|<],[🟩]split[|]butfirst[]butlast[]]"> 
<$let range🟦={{{ [<cell>split[🟦]count[]subtract[1]compare:number:gt[0]] }}}
          range🟩={{{ [<cell>split[🟩]count[]subtract[1]compare:number:gt[0]] }}}>
<$list filter="[range<range🟦>compare:number:gt[0]]">0 </$list>
            <$text text={{{ [[1]add<range🟦>add<range🟩>]  }}}/>
            <$list filter="[range<range🟩>compare:number:gt[0]]">0 </$list>
</$let>

</$list>
)
</$list>

</$let>


The result:

For the full guacamole (the “here” to “there” thinking):

<$let wikitextTable="""|Cell1 |Cell2 |Cell3 |Cell4 |
|Cell5 |Cell6 |Cell7 |<|
|Cell5 |~|Cell7 |Cell8 |
|>|>|Cell10 |Cell11 |
|>|>|Cell10 |<|
|>|>|<|Cell11 |""">

! wikitextTable as-is

<<wikitextTable>>

<hr>

! wikitextTable, text-ified rows

<$list filter="[<wikitextTable>splitregexp[\n]]">
{{!!title}} <br>
</$list>

<hr>

! wikitextTable, text-ified rows, prepping content


<$list variable="row" filter="[<wikitextTable>splitregexp[\n]]"> 
<hr style="border:1px solid red">
row: <<row>>
<hr style="border:1px solid red">
<$list variable="cell" filter="[<row>search-replace:g[>|],[🟦]search-replace:g[|<],[🟩]split[|]butfirst[]butlast[]]"> 
<<cell>>
<hr>
</$list>
</$list>

<hr>

! wikitextTable, text-ified rows, setting up numbers


<$list variable="row" filter="[<wikitextTable>splitregexp[\n]]"> 
<hr style="border:1px solid red">
row: <<row>>
<hr style="border:1px solid red">
(
<$list variable="cell" filter="[<row>search-replace:g[>|],[🟦]search-replace:g[|<],[🟩]split[|]butfirst[]butlast[]]"> 
<$let range🟦={{{ [<cell>split[🟦]count[]subtract[1]compare:number:gt[0]] }}}
          range🟩={{{ [<cell>split[🟩]count[]subtract[1]compare:number:gt[0]] }}}>
<$list filter="[range<range🟦>compare:number:gt[0]]">0 </$list>
            <$text text={{{ [[1]add<range🟦>add<range🟩>]  }}}/>
            <$list filter="[range<range🟩>compare:number:gt[0]]">0 </$list>
</$let>

</$list>
)
</$list>

</$let>

All of that should have some validation added:

  • check that the first cell in the row isn’t “|<|”, and handle that accordingly
  • check that the last cell in the row ins’t “|>|”, and handle that accordingly
2 Likes

Hi @Charlie_Veniot and thanks for your help!
I got some new insights from your approach!

I cannot use a list widget though, I need to use filter runs in functions and store the results in variables

Use of list widgets is just the quickest way (no fuss, no muss) to demonstrate a “process”. It is meant to be “descriptive”, not “prescriptive”.

That is how everybody should use any “solution”.

I expect any snippets I provide to be studied for the description of the process (the mental gymnastics of getting from “A” to “Z”), so that you can then implement your solution.

Well, life does have a way of occasionally confounding my expectations.