What's the best way to extract a single value from a Set in groovy? - 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! :)

Related

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

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())].

Access specific index of array with Pug

How can you display a specific item in an array with Pug? For example:
each answer in answers
li!= answer.Response
Will display each item in the array. But, say I wanted just the the third item or, better yet, pass a variable for a specific index to display. What is the syntax for this?
- const indexIwant = 2;
if answers && answers.length>indexIwant
li=answers[indexIwant]
You need to ensure answers is not null and has at least the number of items to include the indexed item you want.
Another thing: don't use != unless you know exactly what data you are handling.
The simplest way to access a specific index of an array in pug:
-const meals = ["breakfast", "lunch", "dinner"]
-const favoriteDishes = ["coffee & doughnut salad","cheese danish soup","red wine","banana split sandwich"]
-const sides = ["ranch dressing","chutney","ketchup","chocolate sauce"]
p I reckon I will fix myself a hefty helping of #{favoriteDishes[2]} for #{meals[0]} with a side of #{sides[2]}.
Considering that indentation and whitespace is everything in jade / pug, this works :))

Dict key getting overwritten when created in a loop

I'm trying to create individual dictionary entries while looping through some input data. Part of the data is used for the key, while a different part is used as the value associated with that key. I'm running into a problem (due to Python's "everything is an object, and you reference that object" operations method) with this as ever iteration through my loop alters the key set in previous iterations, thus overwriting the previously set value, instead of creating a new dict key and setting it with its own value.
popcount = {}
for oneline of datafile:
if oneline[:3] == "POP":
dat1, dat2, dat3, dat4, dat5, dat6 = online.split(":")
datid = str.join(":", [dat2, dat3])
if datid in popcount:
popcount[datid] += int(dat4)
else:
popcount = { datid : int(dat4) }
This iterates over seven lines of data (datafile is a list containing that information) and should create four separate keys for datid, each with their own value. However, what ends up happening is that only the last value for datid exist in the dictionary when the code is run. That happens to be the one that has duplicates, and they get summed properly (so, at least i know that part of the code works, but the other key entries just are ... gone.
The data is read from a file, is colon (:) separated, and treated like a string even when its numeric (thus the int() call in the if datid in popcount).
What am I missing/doing wrong here? So far I haven't been able to find anything that helps me out on this one (though you folks have answered a lot of other Python questions i've run into, even if you didn't know it). I know why its failing; or, i think i do -- it is because when I update the value of datid the key gets pointed to the new datid value object even though I don't want it to, correct? I just don't know how to fix or work around this behavior. To be honest, its the one thing I dislike about working in Python (hopefully once I grok it, I'll like it better; until then...).
Simply change your last line
popcount = { datid : int(dat4) } # This does not do what you want
This creates a new dict and assignes it to popcount, throwing away your previous data.
What you want to do is add an entry to your dict instead:
popcount[datid] = int(dat4)

Updating a single field in a record with Haskell #

I need to update one field of a very large default record.
As the default may change I don't want to rebuild the entire record manually.
Now I have come across the following way of doing this, but I am not sure how it works:
unaggregate :: MyResult -> MyResult
unaggregate calc#MyResult{..} = calc{ the_defaults = the_override
`mappend` the_defaults }
where
the_override = create ("aggregation" := False)
I have tried searching for 'Haskell # operator' in Google but it does not return immediately useful information.
I saw somewhere calc#MyResult{..} does pattern matching on variables but I don't see what variable calc does for the MyResult record...
Also I have looked up mappend (and Monoids) and I am not sure how these work either...
Thank you for any help
The # symbol is called an "as-pattern". In the example above, you can use calc to mean the whole record. Usually you'd use it like this: calc#(MyResult someResult) -- so you can have both the whole thing and the pieces that you're matching. You can do the same thing with lists (myList#(myHead:myTail)) or tuples (myTuple#(myFst, mySnd). It's pretty handy!
MyResult{..} uses RecordWildcards. Which is a neat extension! BUT RecordWildcards doesn't help you update just one field of a record.
You can do this instead: calc { theFieldYouWantToUpdate = somethingNew }.

What do empty square brackets after a variable name mean in Groovy?

I'm fairly new to groovy, looking at some existing code, and I see this:
def timestamp = event.timestamp[]
I don't understand what the empty square brackets are doing on this line. Note that the timestamp being def'd here should receive a long value.
In this code, event is defined somewhere else in our huge code base, so I'm not sure what it is. I thought it was a map, but when I wrote some separate test code using this notation on a map, the square brackets result in an empty value being assigned to timestamp. In the code above, however, the brackets are necessary to get correct (non-null) values.
Some quick Googling didn't help much (hard to search on "[]").
EDIT: Turns out event and event.timestamp are both zero.core.groovysupport.GCAccessor objects, and as the answer below says, the [] must be calling getAt() on these objects and returning a value (in this case, a long).
The square brackets will invoke the underlying getAt(Object) method of that object, so that line is probably invoking that one.
I made a small script:
class A {
def getAt(p) {
println "getAt: $p"
p
}
}
def a = new A()
b = a[]
println b.getClass()
And it returned the value passed as a parameter. In this case, an ArrayList. Maybe that timestamp object has some metaprogramming on it. What does def timestamp contains after running the code?
Also check your groovy version.
Empty list, found this. Somewhat related/possibly helpful question here.
Not at a computer, but that looks like it's calling the method event.timestamp and passing an empty list as a parameter.
The same as:
def timestamp = event.timestamp( [] )

Resources