How can I qualify a child count to only include some children?


(Malcolm Coad) #1

I want to include a count of top level notes within a container in the container’s subtitle, but excluding outline separators and secondary notes. It’s easy to create a basic rule to count child notes ($Subtitle=$ChildCount), but this pulls in everything. How can I qualify $ChildCount so as to exclude the separators and notes I don’t want, or conversely to include only notes matching specified criteria (for example, all those based on a particular Prototype)? Or is there some other way of achieving the same?

Apols if this is a newbie query, but getting the hang of constructing more complex actions and rules ain’t easy. There are some suggestions in the documentation (e.g. Actions and Dashboards.pdf) but I can’t find anything more thorough. There’s one count item in the Cookbook (under Expressions) but it’s rather specific.


(Galen Menzel) #2

You can use sum_if, which takes an arbitrary filter expression.

To set the subtitle to the child count excluding separators, you can set the $Rule for the container to

$Subtitle=sum_if(children,!$Separator,1)

To only count children with a $Prototype of “foo”, you can use

$Subtitle=sum_if(children,$Prototype=="foo",1)


(Mark Anderson) #3

Use sum_if() Let’s say you want the count of children of prototype ‘pArticle’:

sum_if(children, $Prototype=="pArticle",1)

What you are doing is collecting a list of qualifying objects (i.e. a sub-set of the children) setting a value of 1 for each item and returning the sum of those values - i.e. your modified child-count.

Edit:
Ah, @galen beat me to it, but happily we’re in accord. Seeing his examples, reminds me to point out that the second ‘filter’ input to sum_if() is actually a query, i.e. the syntax you use in an agent’s query or in find(). Thus the filter could be more than one test. For instance, counting all children that aren’t of prototype ‘pArticle’ and are not separators:

sum_if(children, $Prototype!="pArticle"& !$Separator,1)

The sum_if parameters are separated by commas but f it helps you understand the process better you can safely put parentheses around your query. So the above can also be:

sum_if(children, ($Prototype!="pArticle"& !$Separator),1)


(Malcolm Coad) #4

Many thanks, Mark and Galen. This is perfect - and the link to the Full Operator List means I’m now truly on the road to enlightenment. And thanks for the amplification, Mark. Much appreciated, both.


(jmm) #5

The code below counts the number of words in annotations that are descendants of the containter in which I have placed it as a rule. But number of notes and annotions is 0, I cannot understand why.

$Text=sum_if(descendants, ($Prototype=="pAnnotation" & !$IsAlias),1) + " annotations, " + sum_if(descendants, ($Prototype=="pAnnotation" & !$IsAlias),$WordCount) + " words \n" + sum_if(descendants, ($Prototype=="pNote" & !$IsAlias),1) + " notes"


(Mark Anderson) #6

The code works for me. See my annotation-test.tbx (68.3 KB) file.

Can you link to a file that shows the problem you describe.


(eastgate) #7

I’d recommend breaking this big rule into pieces, at least for preliminary testing, just because it’s beginning to be a bit complicated. For example, if we try

  $MyNumber=sum_if(descendants, ($Prototype=="pAnnotation" & !$IsAlias),1) ;

it is easy to see whether that part of the expression is doing what you expect. Then, you can assemble $Text from the intermediate results, which separates the formatting from the computation.

Note, too, that your rule needs to look at every descendant of this note three separate times. That might not be a problem, but might involve a lot of work. It might be neater to have an agent gather the annotations

 name: /Annotations
 query: $Prototype=="pAnnotation"

and then we can simply look at the children of this agent.


(jmm) #8

If I understand well your file, there are 2 original annotations in the Test container, with 6 words. But the counting says 3 annotations with 10 words.
Thanks for your kind attention once more.


(jmm) #9

Sorry, @mwra. I missed counting one nested note in your file. Yet the same code doesn’t work in my file!

I’am basically happy to start using my file as it is set up, but it crashes too often, so I will be grateful for any other suggestions to optimize it.

I will send my file once I have the time to clear it up.


(eastgate) #10

Have you sent sample files and crash logs to tech support?


(jmm) #11

I will do so next time it happens, thank you. As safeguards against crashing, I have automated the zipping of copies of my tbx file, since Time Machine doesn’t make copies when I would need them. I have also opted not to automate the contents of $Name attributes ($DisplayName and $DisplayExpression) and of $Text, as I have ended up with emptied notes which I had not noticed, due to my own code mistakes.

I am learning to set my tbx file up, and for the time being prone to make mistakes. Other than this temporary situation, I am happy with what can be achieved with Tinderbox.