Tinderbox Forum

How does sorting work in rules?


(alj ) #1

I need help to understand how TBX’s sorting works when writing rules. In the end, what I’m trying to do is set the $Text of a note to be equal to the combined $Texts of that note’s inbound linked notes… and sorted by note creation date (i.e. the oldest linked note at the top or bottom in the resulting list).

I wrote the rule in the attached screenshot (using $Created to hide the content).

$Text=(links.inbound..$Created).sort($Created).format("\n")

What I would expect to see when sorting by $Created:

2019-01-27T20:41:05-04:00
2019-02-14T10:16:56-04:00
2019-03-22T22:33:24-04:00

Instead, I see a seemingly random order of datestamps (in screenshot). Can anyone shed light on what I’m doing wrong?

Bitmap


(alj ) #3

I tried copying/pasting your Rule and it just left a blank Text area for the note in question. So, I’m still at a loss.

Is there some foundational “thing” that I’m missing about Rules on notes? Specifically, I can’t seem to place line breaks in my Rule; pressing enter or shift+enter just highlights the Rule text… why can’t I format the Rule with line breaks to make it easy to read?


(Mark Anderson) #4

As $Created is a read-only, I’ve used $MyDate to date, with 3 notes with $MyDate set, via KA, to ‘now’, ‘yesterday’ and ‘tomorrow’ - IOW 3 notes all one day apart. I than applied this rule:

$Text=(links.inbound..$MyDate).sort.format("\n")

links() returns a list of dates (i.e. date/time date type data). The default .sort order for dates is eralier -> later and this is what I see:

Untitled%202019-03-23%2015-37-21

I’m unclear as to why you want to use use a sort(value) value. The latter form is intended where you wish to sort a list of paths (or unique titles) based on a given attributes those notes’. If I use the rule:

$Text=(links.inbound..$Name).sort($MyDate).format("\n")

I get my test notes sorted in the order of their $MyDate info, which as can be seen us noit their outline order:

Untitled%202019-03-23%2015-43-28

IOW, only use a .sort value if you want to sort a list of titles/paths in an order other than their outline order. If you are retrieving lists of date or number type attributes the default .sort should work as you’'d expect. See more here.

Does this help?


(alj ) #5

Thanks for all your replies so far. I’m getting a better sense of my lack of understanding of TBX’s code so far.

@mwra Your $Text=(links.inbound..$Name).sort($MyDate).format("\n") code works well in that case, but does not work for me when I change the $Name to $Text – i.e. $Text=(links.inbound..$Text).sort($Created).format("\n");.

I think I know why; I think it’s related to me trying to apply sort to a list of text, rather than to a set of notes.


Here’s how I solved it. Let me know if there’s a more concise way:

(1) I assemble a list of note $Names, sorted by their creation date (in reverse).

$MyList=(links.inbound..$Name).sort($Created).reverse();

(2) I use that list to assemble a new list of note $Texts. In the end, I want to get $Text; I don’t care about their $Names. But, I needed the $Names in order for sort to work in step 1.

$MyList=collect($MyList,$Text);

(3) I set the note-in-question’s $Text to be this new list, and pop a line-break in there between each incoming $Text.

$Text=$MyList.format("\n");

(Mark Anderson) #6

Sadly, v. busy here, so no time to build a test doc, but…

You could likely make the above into one rule:

$Text=(collect((links.inbound..$Name).sort($Created).reverse)).format("\n")

Essentially this condenses your 3 steps into one. Note that when doing this sometimes it helps to add parentheses around a query-driven step in the process before dot-chaining another task. This helps ensures Tinderbox fully completes the query before trying to act full upon it. Thus, above the links() call and chained sort is in fully enclosed in discrete parentheses within the collect() call.

That said, apart form brevity of code, I’m not sure the above is any faster than this:

$MyList=(links.inbound..$Name).sort($Created).reverse();
$MyList=collect($MyList,$Text);
$Text=$MyList.format("\n");
$MyList=;

Indeed, the latter is probably more easily understood when you decide to revisit months later. Notre the final step to avoid constantly caching what might be a big list. Also, consider using an edict rather than a rule. Think of an edict as a lazy rule - i.e. run infrequently - yet which can still be run on demand if needs be. Otherwise it is easy for your doc to incrementally add lots of rules running unnecessarily often and potentially affecting the speed of general updating.

Does that help?


(alj ) #7

Also, consider using an edict rather than a rule … Otherwise it is easy for your doc to incrementally add lots of rules running unnecessarily often and potentially affecting the speed of general updating.

That’s valuable information!

Essentially this condenses your 3 steps into one.

In my opinion, combining three lines into one line (containing the same characters) makes code pointlessly difficult to understand… I’m happy with where we landed with multi-line :smile:


(alj ) #8

For anyone who got here searching for how to put line breaks in Tinderbox code windows, use option + return… not knowing that frustrated me much more than it should have.


(Mark Anderson) #9

If I’m noodling with long bits of code, I often use a note set to use the built-in ‘Code’ prototype, or I use an external code editor (for me: BBEdit or Sublime Text). If you use whitespace (spaces or tabs) to lay out things like nested if conditionals or .each loops, Tinderbox will ignore the ‘formatting’ if copy/pasted to a rule/edict/action input box.


(alj ) #11

True, but I like line-breaks :slight_smile: