Return True if Array Contains a Specific String - JSONata - jsonata

Is there a way in JSONata to have a function return TRUE if it finds a specific string within a provided array? For example I have an array of colors:
const myArray = [red,blue,green,pink]
I am trying to figure out an expression that would search that array for "blue" and return true if it finds the value.
On the JSONata documentation, I found a function called $boolean(arg)that I think I would need to use but I'm not sure how to implement it. The documentation shows an argument type option as "array: contains a member that casts to true", but I can't really tell how to implement it.
Would it be as simple as $boolean(myArray, "blue")?

The in operator is what you need. See https://docs.jsonata.org/comparison-operators#in-inclusion
In your case, the expression "blue" in myArray will return true. See https://try.jsonata.org/r0q7GnSOh

edit: Thought this was python, but maybe you could use something similar for JSONata
you can make a for loop with an if condition to check your condition
listOfStrings = ['red','green','blue']
for strings in listOfStrings:
if listOfStrings[strings] == 'blue':
return True

Related

How to convert string to Xpath in Xquery function (BaseX)

I am writing Xquery function for BaseX which gets one of arguments as name of the element node. This name is then used in Xpath, but in general I cannot convert string to element.
This is how the method looks like
declare function prefix:getElementWithValue($root as document-node()?, $elem as xs:string?, $minVal as xs:float?, $maxVal as xs:float?)
as element()*
{
let $e := element {$elem} {""}
for $x in $root//SUBELEM
return if ($x//$e/#ATTRIB>=$minVal and $x//$e/#ATTRIB<=$maxVal) then ($x)
};
and the call
return prefix:getElementWithValue($db, "SomeElem", 10.0, 10.0)
and I am getting empty response from that. If I replace the $x//$e with $x//SomeElem it returns proper response. From the QueryPlan I see that the $e is treated as literal value. XPATH is not $x//SomeElem/#ATTRIB but $x//$e/#ATTRIB
So my question is how to covert string to type that can be used in XPATH?
XQuery does not have a standard function to evaluate a dynamically-constructed XPath expression.
Many XQuery processors offer some kind of extension function that does this, however. For example, BaseX offers query:eval():
https://docs.basex.org/wiki/XQuery_Module#xquery:eval
Note that variables in XQuery represent values, not fragments of expression text. Your expression $x//$e/#ATTRIB is equivalent to $x//"SomeElem"/#ATTRIB, which is quite different from $x//SomeElem/#ATTRIB.
If you know that $elem will always be an element name, then you can write $x//*[name()=$e]/#ATTRIB. But take care over namespaces.

Rails dynamic params.require(...).permit(...) syntax?

I can do this code:
params.require(:something).permit(:param_a,:param_b)
And this:
params.require(:something).permit(:param_a,:param_c_attributes:[])
My problem is that I need to select the permit parameters depending if some parameter exists. So I tried:
premit_params = {:param_a,:param_c_attributes:[]}
premit_params = {:param_a,:param_d} if params[:something] && params[:something][:param_d]
params.require(:something).permit(premit_params)
But it's not working.
BTW: Using Rails 5.1
It doesn't work because permit doesn't expect a hash as an argument, but a list of parameters.
Collect your arguments in an array and split that array with the splat operator (*) to list or arguments:
premit_params = [:param_a, { :param_c_attributes: [] }]
premit_params = [:param_a, :param_d] if params.dig(:something, :param_d)
params.require(:something).permit(*premit_params)
You can check if the parameter you want exits
For Example:
if (user_params.has_key?(:name))
end
Moreover, parameters are saved in hash so you have different methods you can use to apply your logic
https://ruby-doc.org/core-1.9.3/Hash.html

How to use .contains with array?

I have an array in a document that contains a list of user ids.
I'd like to find all documents that have this list of user ids.
I know I can do something like:
r.db('unicorn')
.table('rooms').filter(function(doc){
return doc('people').contains(
"id-one","id-two"
)
})
I know this will work great, but I have to hardcode things. How do I pass the contains function an array of values to match against?
After a little digging, The simplest solution was to use args. Was a bit non-obvious from the examples. This way I can pass in dynamic values and run commands with them.
r.db('unicorn')
.table('rooms').filter(function(doc){
return doc('people').contains(
r.args(["id-one","id-two"])
)
})
You can use setIntersection and pass array:
r.db('unicorn')
.table('rooms').filter(function(doc){
return doc('people').default([]).setIntersection(
["id-one","id-two"]
).count().eq(2)
})
So, if you have array:
var myArr = ["id-one","id-two"];
You can write query like this:
r.db('unicorn')
.table('rooms').filter(function(doc){
return doc('people').default([]).setIntersection(myArr).count().eq(myArr.length)
})

MarkLogic: how to search for an XPath using cts:uris

Is it possible to search for a uri whose document contains a certain XPath using cts:uris()? I thought it may be quicker than returning uris from a cts:search. Here is what I have currently:
declare function local:xpath-search($collection) {
for $i in cts:search(//a/b, cts:and-query((cts:collection-query($collection)) ))[1] return fn:base-uri($i)
} ;
Is there a quicker way to return documents that contain a match to the XPath //a/b, using cts:uris()?
You can use cts:element-query() to construct a cts:query that functions similar to the XPath expression //a/b searching for documents that have a elements that have b element descendants. It isn't exactly the same, and might give you some false positives, because it is really more akin to //a//b, but might be acceptable and can be used with cts:uris().
xquery version "1.0-ml";
declare function local:xpath-search($collection) {
cts:uris("", (),
cts:and-query((
cts:collection-query($collection),
cts:element-query(xs:QName("a"),
cts:element-query(xs:QName("b"), cts:and-query(()) ) ) )) )
};

Create an object if one is not found

How do I create an object if one is not found? This is the query I was running:
#event_object = #event_entry.event_objects.find_all_by_plantype('dog')
and I was trying this:
#event_object = EventObject.new unless #event_entry.event_objects.find_all_by_plantype('dog')
but that does not seem to work. I know I'm missing something very simple like normal :( Thanks for any help!!! :)
find_all style methods return an array of matching records. That is an empty array if no matching records are found. And an empty is truthy. Which means:
arr = []
if arr
puts 'arr is considered turthy!' # this line will execute
end
Also, the dynamic finder methods (like find_by_whatever) are officially depreacted So you shouldn't be using them.
You probably want something more like:
#event_object = #event_entry.event_objects.where(plantype: 'dog').first || EventObject.new
But you can also configure the event object better, since you obviously want it to belong to #event_entry.
#event_object = #event_entry.event_objects.where(plantype: 'dog').first
#event_object ||= #event_entry.event_objects.build(plantype: dog)
In this last example, we try to find an existing object by getting an array of matching records and asking for the first item. If there are no items, #event_object will be nil.
Then we use the ||= operator that says "assign the value on the right if this is currently set to a falsy value". And nil is falsy. So if it's nil we can build the object form the association it should belong to. And we can preset it's attributes while we are at it.
Why not use built in query methods like find_or_create_by or find_or_initialize_by
#event_object = #event_entry.event_objects.find_or_create_by(plantype:'dog')
This will find an #event_entry.event_object with plantype = 'dog' if one does not exist it will then create one instead.
find_or_initialize_by is probably more what you want as it will leave #event_object in an unsaved state with just the association and plantype set
#event_object = #event_entry.event_objects.find_or_initialize_by(plantype:'dog')
This assumes you are looking for a single event_object as it will return the first one it finds with plantype = 'dog'. If more than 1 event_object can have the plantype ='dog' within the #event_entry scope then this might not be the best solution but it seems to fit with your description.

Resources