Counting the number of all options in a select_one / select_multiple variable

Hello,

I have a select_one variable on my ODK form.

1.I want to count the number of all options

any ideas

Hi @yabasha,

Can you provide more description of your problem? With example.

You can use count-selected() to count the number of selected items.

Checkout more info here https://docs.opendatakit.org/form-operators-functions/?highlight=count%20selected#count-selected

are you willing to randomize them...?

1 Like

I don't think so... it's not the first question about calculating all possible options in select one and select multiple. I have seen at least two similar questions.
As I know it's not possible so if I'm correct and as I said it's not the first question maybe we should add such an option. @yanokwa what do you think?

I asked ‘cause you can use a ‘trick’ - if you randomize them it’ll convert the control’s options list to a nodeset, which you can then count()...

But yes, especially when pulling in option lists from external datasets, I agree that being able to determine the numbers of options would be quite useful (less critical for hard coded options since the form writer knows how many they added).

1 Like

I created an issue on the Javarosa repository https://github.com/opendatakit/javarosa/issues/400

I'll move this conversation into Features so we can discuss it there.

@Xiphware Since you are becoming the person who adds things to JavaRosa, any ideas on how we should do this?

Probably in terms of usability, the most obvious approach would be adding a new custom XPath function for this purpose, eg count-options(${my_select_question}), since that's how form writers are familiar with dealing with select_ones and select_multis (eg selected(), count-selected()...).

Although in terms of actual underlying implementation it may be quite a different beast, since we're not merely processing the contents of a node in the instance XML; in many (simple) cases the options list may not even exist in as an XML instance in the XForm definition, and only be defined as part of the control's <item> list. Probably it'll require identifying the associated control/question, and then looking up all the options wherever they've persisted after parsing (in my case, the options table in my internal DB). But hey, that's all merely 'implementation details', eh... :wink:

So does count-options(${my_select_question}) make sense?

1 Like

Thank you @Xiphware for your comments and yes that's what I want to use count-options(${Q1}) and I hope soon this function will be added

easier said than done... :wink: . But I think we've probably got a reasonable consensus that such a thing is worthwhile, eh. :slight_smile:

I'll wait for a bit more feedback - @martijnr? @ggalmazor? @yanokwa? - about a count-options() XPath function, and if OK I'll open a javaRosa github issue to track. I might be able to work on something, but I cant promise exactly when a PR will be ready.

count-options(${Q1}) as an XPath function does not seem right to me, because the nodes do not exist in the primary instance, as @xiphware mentioned.

Since we are talking about itemsets (only, right?), the solution in XForms already exists (count()), so I think we should (only) look into a way to make it easier to use this in XLSForm.

Perhaps count-options(${Q1}) could be translated to count(instance('a')/path/to/nodes) by pyxform by extracting the itemset content of Q1 and copying it as a parameter of count().

1 Like

The problem, as I see it, is there is no requirement (at least in XForms, and possibly in ODK/javaRosa?) for the options of a select to be converted into an itemset (with which to then count). For example, in the following very simple XML form containing a single select1, created in and exported from Kobo:

<?xml version="1.0"?>
<h:html xmlns="http://www.w3.org/2002/xforms" xmlns:ev="http://www.w3.org/2001/xml-events" xmlns:h="http://www.w3.org/1999/xhtml" xmlns:jr="http://openrosa.org/javarosa" xmlns:odk="http://www.opendatakit.org/xforms" xmlns:orx="http://openrosa.org/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <h:head>
    <h:title>countoptions</h:title>
    <model>
      <instance>
        <data id="snapshot_xml">
          <select_1/>
          <meta>
            <instanceID/>
          </meta>
        </data>
      </instance>
      <bind nodeset="/data/select_1" required="false()" type="select1"/>
      <bind calculate="concat('uuid:', uuid())" nodeset="/data/meta/instanceID" readonly="true()" type="string"/>
    </model>
  </h:head>
  <h:body>
    <select1 ref="/data/select_1">
      <label>please select 1</label>
      <item>
        <label>Option 1</label>
        <value>option_1</value>
      </item>
      <item>
        <label>Option 2</label>
        <value>option_2</value>
      </item>
      <item>
        <label>Option 3</label>
        <value>option_3</value>
      </item>
      <item>
        <label>Option 4</label>
        <value>option_4</value>
      </item>
      <item>
        <label>Option 5</label>
        <value>option_5</value>
      </item>
    </select1>
  </h:body>
</h:html>

...there is no instance('a')/path/to/nodes itemset to count(), right?!

It would seem that unless we want to introduce a new requirement that all select options must now be represented as an itemset (which the above Kobo form apparently does not), I don't think we can rely on the existing count() function. Or am I missing something?

Yup, specifying the desired select_one or select_multi control in the XPath function using ${Q1} [or in reality, /instance/data/Q1...), of whose options you want to count, would be tricky to implement. But from this nodeset ref we should be able to uniquely determine the binding and control of the actual select question's control itself, from which we can (hopefully) locate its corresponding itemset or item list. I just cant think of better way by which a (potentially XForm illiterate) XLSForm writer can uniquely identify a select question, except via the control's node ref: ${Q1}, aka instance/data/Q1

[hence my earlier comment, "easier said than done"... :wink: ]

Hi all,
Any updates on this please?
Thanks

Bump. No updates AFAIK. But perhaps we should resurrect a discussion as to perhaps how best go about offering such a feature. As @martijnr indicates, if these options are already in an explicit itemset then a solution already exists. However if not - as in my above example of a basic XForm - the XPath count() approach wont work. But then in that case these are arguably statically declared options in any case, so the form writer already knows what the count is [sic].

Perhaps an option might be to introduce something similar to randomize() - which as a side effect turns an option list into an itemset - but in this case not randomize them. And by doing so expose the options to be counted via count(). Call it say itemset()?

Thoughts? @ln?

The first question I have is whether there is actually any benefit to pyxform generating static choice lists rather than always using secondary instances. See https://github.com/XLSForm/pyxform/issues/203 for some discussion about that. It's not uncommon for me to add bogus choice filters in order to force instance creation. That's what I would do in this case rather than randomizing the order of the values. I think it would be ideal to always generate instances for selects since those provide a lot of power, including for this situation.

I'm guessing that in this case people are using search() or "fast itemsets". I would not be inclined to add functionality to those since they are on a deprecation path.

1 Like

First, although we could certainly adjust pyxform to generate secondary instances for choice lists, I'd [selfishly] prefer if this could be configurable behavior. Also it doesn't really address the fact that choice lists are after all standard XForm, so a general purpose (XPath?) solution - to counting the number of choices in a select/select1- that now requires that the ultimate (XML) XForm to have been generated via XLSForm doesn't quite seem right...

Counting choices in a static select doesn't make much sense, does it? If the choices are static, then the person designing the form knows exactly how many there are (as you pointed out previously, @Xiphware) . The counting is only useful if that count can actually change.

Taking a step back, here, I think before going too far down brainstorming around a feature, we should be really clear on what the user story is because there are so many great ideas that also need attention!

In this case it would be helpful to get examples of when counting all the options is helpful and to be really explicit about what data sources users want to leverage. My guess is that this all gets resolved once users use spec-compliant secondary external instances.