Does 'position()' have to be explicitly included in this Xpath? - position

This returns all the first 'nd's as expected
select="osm/way/nd[1]"
This returns all the lasts:
select="osm/way/nd[last()]"
This returns both:
select="osm/way/nd[position() = 1 or position() = last()]"
Is there a syntax to remove position() function?
Something like this, but works?
select="osm/way/nd[[1] or [last()]]"

There has been some debate about allowing a new syntax to select a range https://github.com/qt4cg/qtspecs/issues/50#issuecomment-799228627 e.g. osm/way/nd[#1,last()] might work in a future XPath 4 but currently it is all up in the air of a lot of debate and questionable whether a new operator is helpful instead of doing osm/way/nd[position() = (1, last())].

Related

Not able to use for loop in ternary operator in arangodb

How do we write conditions in arango, that includes for loops. I can elaborate the requirement below.
My requirement is if a particular attribute(array type) exists in the arango collection, i would read data from the collection(that requires a loop) or else, might do the following :
return null
return empty string ""
do nothing.
Is this possible to achieve in arango?
The helping methods could be -->
-- has(collectionname, attributename)
-- The ternary operator ?:
let attribute1 = has(doc,"attribute1") ?(
for name in doc.attribute1.names
filter name.language == "xyz"
return name.name
) : ""
But this dosent work. Seems like arango compiler first attempts to compile the for loop, finds nulls and reports error as below. Instead, it should have compiled "has" function first for the ternary operator being used.
collection or array expected as operand to FOR loop; you provided a value of type 'null' (while executing)
If there is a better way of doing it, would appreciate the advice!!
Thanks in advance!
Nilotpal
Fakhrany here from ArangoDB.
Regarding your question, this is a known limitation.
From https://www.arangodb.com/docs/3.8/aql/fundamentals-limitations.html:
The following other limitations are known for AQL queries:
Subqueries that are used inside expressions are pulled out of these
expressions and executed beforehand. That means that subqueries do not
participate in lazy evaluation of operands, for example in the ternary
operator. Also see evaluation of subqueries.
Also noted here for the ternary operator:
https://www.arangodb.com/docs/3.8/aql/operators.html#ternary-operator.
An answer to the question what to do may be to use a FILTER before enumerating over the attributes:
FOR doc IN collection
/* the following filter will only let those documents passed in which "attribute1.names" is an array */
FILTER IS_ARRAY(doc.attribute1.names)
FOR name IN doc.attribute1.names
FILTER name.language == "xyz"
RETURN name.name
Other solutions are also possible. Depends a bit on the use case.

Converting match object to string in perl6

I was trying to convert a match object to a string in perl6. The method Str on a match object is defined as:
method Str(Match:D: --> Str:D)
I would think I could use Str($match) to accomplish this. And it seems to convert it to a string, but I'm getting an error using the string with the following code:
my $searchme = "rudolph";
my $match = $searchme ~~ /.*dol.*/;
say $match.WHAT;
my $test1 = Str($match);
say $test1.WHAT;
say $test1;
With the output:
(Match)
(Str)
With the error:
Cannot find method 'gist': no method cache and no .^find_method in
block at .code.tio line 6
However, if I run:
my $searchme = "rudolph";
my $match = $searchme ~~ /.*dol.*/;
say $match.WHAT;
my $test1 = $match.Str;
say $test1.WHAT;
say $test1;
I get no error and the result:
(Match)
(Str)
rudolph
Is this a bug or me misunderstanding how it works?
Thanks for reading.
I'm writing this up as an answer even though it's actually an incomplete discussion of a bug, so not at all normal SO fare. The alternative of lots of comments doesn't seem better.
It's a bug. Perhaps you just golfed this.
dd $test1; instead of say $test1; is helpful in that it displays BOOTStr $test1 = (BOOTStr without .perl method).
Based on that I searched the rakudo repo for BOOTStr and that led to the above issue.
Golfing it further leads to:
say $ = Str(Match.new);
Note that these are all fine:
say Str(Match.new);
say $ = Int(Match.new);
say $ = Str(Date.new: '2015-12-31');
It appears to be a combination of leaking some implementation details regarding how Rakudo/NQP/MoarVM bootstrap; Match being an NQP object; Str() on that being wonky; and assigning it to a Scalar container (the $ is an anonymous one) making that wonkiness visible.
I'll add more when/if I figure it out.

Checking for Item in a List Box Ignoring Case

Having an issue with a bit of code designed to add an email alias to a list box. I have a check built in to ensure the item you attempt to add isn't already in the list, but the check is case sensitive when I don't want it to be. I'm not sure how to make it ignore the case... Here's my code:
Dim ItemToAdd as String = ""
ItemtoAdd = tbxItemtoAdd.Text + "#emaildomain.co.uk"
If Not lbxEmailAliases.Items.Contains(ItemtoAdd) Then
lbxEmailAliases.Items.Add(ItemtoAdd)
End If
At the moment if the list box contains johnsmith24#emaildomain.co.uk and you try to add Johnsmith24 (capital J), it will add this successfully, but I don't want it to do that. How do I get it to ignore case?
I've tried changing lbxEmailAliases.Items.Contains(ItemtoAdd) to lbxEmailAliases.Items.Contains(ItemtoAdd, StringComparison.CurrentCultureIgnoreCase) but it's not happy with this as there are too many arguments, it will only take one.
Any ideas please?
If this is a standard WinForm ListBox control, then there is no way to do it without looping through all of the items and checking each one individually. For instance:
Dim found As Boolean = False
For Each item As Object In ListBox1.Items
found = item.ToString().Equals(ItemToAdd, StringComparison.CurrentCultureIgnoreCase)
If found Then
Exit For
End If
Next
If found Then
lbxEmailAliases.Items.Add(ItemtoAdd)
End If
However, if you are comfortable with LINQ, you can do it more concisely like this:
If ListBox1.Items.OfType(Of String).Any(Function(item) item.Equals(ItemToAdd, StringComparison.CurrentCultureIgnoreCase)) Then
lbxEmailAliases.Items.Add(ItemtoAdd)
End If
Or, as Andy G pointed out, the LINQ Contains method is even easier since it accepts an IEqualityComparer and a stock one which supports case insensitive string comparisons is provided by the framework:
If ListBox1.Items.OfType(Of String).Contains(ItemToAdd, StringComparer.CurrentCultureIgnoreCase) Then
lbxEmailAliases.Items.Add(ItemtoAdd)
End If
It should be StringComparer, not StringComparison:
lbxEmailAliases.Items.Contains(ItemtoAdd, StringComparer.InvariantCultureIgnoreCase)
The method accepts an IEqualityComparer, the docs.
As pointed out by Steven Doggart, ListBox Items require the use of OfType(Of T):
lbxEmailAliases.Items.OfType(Of String).Contains(ItemtoAdd, StringComparer.InvariantCultureIgnoreCase)
An alternative could be the FindString-method:
If lbxEmailAliases.FindString(ItemtoAdd) = ListBox.NoMatches Then
lbxEmailAliases.Items.Add(ItemtoAdd)
End If
Note: This method searches for items that start with the specified string and returns the index of the first found item.
Means it will find jdoe#domain.com even if the existing e-mail-address is jdoe#domain.computer.com.
So maybe it's not the best solution for your specific case.
EDIT:
You can use FindStringExact instead. Like this you'll get the wanted case insensitive, non-partial comparison.
If lbxEmailAliases.FindStringExact(ItemtoAdd) = ListBox.NoMatches Then
lbxEmailAliases.Items.Add(ItemtoAdd)
End If

C# 4.0 function to check for first four characters in the string

I need to validate for valid code name.
So, my string can have values like below:
String test = "C000. ", "C010. ", "C020. ", "C030. ", "CA00. ","C0B0. ","C00C. "
So my function needs to validate below conditions:
It should start with C
After that next 3 characters should be numeric before .
Rest it can be anything.
So in above string values, only ["C000.", "C010.", "C020.", "C030."] are valid ones.
EDIT:
Below is the code I tried:
if (nameObject.Title.StartsWith(String.Format("^[C][0-9]{3}$",nameObject.Title)))
I'd suggest a regex, for example (written off the top of my head, may need work):
string s = "C030.";
Regex reg = new Regex("C[0-9]{3,3}\\.");
bool isMatch = reg.IsMatch(s);
This regex should do the trick:
Regex.IsMatch(input, #"C[0-9]{3}\..*")
Check out http://www.techotopia.com/index.php/Working_with_Strings_in_C_Sharp
for a quick tutorial on (among other things) individual access of string elements, so you can test each element for your criteria.
If you think your criteria may change, using regular expressions gives you maximum flexibility (but is more runtime intensive than regular string-element evaluation). In your case, it may be overkill, IMHO.

What's the best way to extract a single value from a Set in groovy?

If I have a Set that I know contains a single element, what's the best way to extract it? The best I can come up with is this, but it doesn't feel very groovy:
set = [1] as Set
e = set.toList()[0]
assert e == 1
If I'm dealing with a list, I've got lots of nice ways to get the element, none of which seem to work with Sets:
def list = [1]
e = list[0]
(e) = list
e = list.head()
One other possibility (which will work in Java or Groovy):
set.iterator().next()
A few alternatives, none of them very pretty:
set.iterator()[0]
set.find { true }
set.collect { it }[0]
Finally, if it's guaranteed that that set has only one item:
def e
set.each { e = it }
The underlying issue, of course, is that Java Sets provide no defined order (as mentioned in the Javadoc), and hence no ability to get the nth element (discussed in this question and this one). Hence, any solution is always to somehow convert the set to a list.
My guess is that either of the first two options involve the least data-copying, as they needn't construct a complete list of the set, but for a one-element set, that should hardly be a concern.
Since Java 8, here is another solution that will work for both Java and Groovy:
set.stream().findFirst().get()
Even when this question is quite old, I am sharing my just a bit prettier solution.
(set as List).first()
(set as List)[0]
If you need to take null into account (not the case in this question):
(set as List)?.first()
(set as List)?.get(index)
Hope it helps! :)

Resources