Sum of nulls to return null - arangodb

How to make
sum(array[*].value) to return NULL if all values are NULL or no values?
Currently it returns 0 in both cases
The best I can think of is
first_document(array[*].value) ? sum(array[*].value) : null
which needs to iterate collection twice
Is there a better way to do it?

How about using a FOR loop instead of the shorthand notation and filter out null values? Then we can check if zero elements remain and return null:
LET tmp = (FOR elem IN array FILTER elem.value != null RETURN elem)
RETURN LENGTH(tmp) ? SUM(tmp) : null
You could also use an array inline expression, but it's about the same amount of characters:
LET tmp = arr[* FILTER CURRENT.value != null RETURN CURRENT.value]
RETURN LENGTH(tmp) ? SUM(tmp) : null

Related

Cant understand what this function does

def is_balanced(input_str):
s = list()
for ch in input_str:
if ch == '(':
s.append(ch)
if ch == ')':
if not s:
return False
s.pop()
return not s
Can anyone explain what is really happening after the line "if ch == ')':" ?
if not s:
checks whether the list is empty or not, if the list is empty then the condition inside is executed.
let's say you provide ())()() in input, so for:
-> the 0th index it will first add ( into s
-> for 1st index (i.e )): it will first check if s is empty or not, as here we have ( in s so the if condition will not execute, then it goes on to pop the value from the list. (notice now the list is empty)
-> on coming to the 2nd index (i.e )): it will first check if the list is empty or not, as the list is empty it will return False

alter map key when there is more than one maximun value on groovy clousure

I Have two maps:
def map = ['a': 3, 'b': 4, 'c':5]
def map2= ['a': 3, 'b': 4, 'c':4]
I want to take the maximum value of the map like this:
def newMap = map.max {it.value}
and my output is correct ('c':5), my problem is with the second map because there is more than one max value. On this case I want to change the key so I can know that there was more than one max value. I want my output to be:
def newMap2 = map2.max {it.value}
assert newMap2 == ['+than1': 4]
Can I alter the key of the map in this specific case using groovy functions?
Can I achieve this inside the max closure?
I do not want to alter the key if there isn't more than one max value.
Keep in mind that map.max(Closure cl) returns Map.Entry<String, Integer> and not a map. So if you expect a map with a single key, you will have to create one from the result you get.
Map.max(Closure cl) searches for the maximum value and returns it. There is no variant that allows you to modify function behavior in case of two entries holding maximum value. According to docs:
Selects an entry in the map having the maximum
calculated value as determined by the supplied closure.
If more than one entry has the maximum value,
an arbitrary choice is made between the entries having the maximum value.
In practice: the first entry found with maximum value is returned.
Groovy however offers a different collection function that can be used to achieve what you expect - Collection.inject(initialValue, closure) function. This is an equivalent of popular fold function known very well in functional programming paradigm. It starts with some initial value and it iterates a collection and applies a function to every element (this function returns a new value that replaces value passed as initial value) to reduce a list of elements to a single element in a single iteration. Collection.inject() javadoc gives a very descriptive example of summing all numbers from a list:
assert 0+1+2+3+4 == [1,2,3,4].inject(0) { acc, val -> acc + val }
Now let's take a look how we can use this function to achieve expected result. Consider following example:
def map2= ['a': 3, 'b': 4, 'c':4]
Tuple2<String, Integer> result = map2.inject(new Tuple2<String, Integer>(null, null)) { Tuple2<String, Integer> tuple, entry ->
entry.value >= tuple.second ?
new Tuple2<>(entry.value == tuple.second ? '+1than1' : entry.key, entry.value) :
tuple
}
assert result.first == '+1than1'
assert result.second == 4
Here we start with new Tuple2<String, Integer>(null, null) as an initial value - a Tuple2 represents a pair of two values. In our case it represents a key and the maximum value. The closure checks if current entry value is higher or equal the one we store in the tuple and if this is true it checks if the value is the same as the one we have already found - if this is true it uses +than1 as a key instead of a key taken from map. Otherwise it simply uses entry key without any modification. When the value is lower then the one we currently store in the tuple, existing tuple gets returned. And finally, we get a tuple where tuple.first holds a key and tuple.second holds a maximum value.
Of course to make the inject part more readable it is worth extracting a data class that represents your expected result and behavior. You can implement a function like compareAndReplace there to define specific behavior when another maximum value is found. Something like this:
import groovy.transform.Immutable
#Immutable
class Result {
static Result EMPTY = new Result(null, null)
String key
Integer value
Result compareAndReplace(Map.Entry<String, Integer> entry, String key = '+1than1') {
entry.value >= value ?
new Result(entry.value == value ? key : entry.key, entry.value) :
this
}
}
def map2 = ['a': 3, 'b': 4, 'c': 4]
Result result = map2.inject(Result.EMPTY) { Result result, entry -> result.compareAndReplace(entry) }
assert result.key == '+1than1'
assert result.value == 4
You can do it in a one-liner but it's still a little obscure:
println map2.groupBy{ it.value }.max{ it.key }.value.with{ it.size() > 1 ? ['+than1': it.values()[0]] : it }
I'd probably at least extract out the last Closure:
def mergedKey = { it.size() > 1 ? ['+than1': it.values()[0]] : it }
def newMap2 = map2.groupBy{ it.value }.max{ it.key }.value.with(mergedKey)
assert newMap2 == ['+than1': 4]

How to sort multi valued list in groovy?

I have list with below values
[
[Invoice Number:452170, Date:12-05-2016, Price:124589.0, Customer Name:David Copperfield],
[Invoice Number:452171, Date:13-04-2014, Price:453212.0, Customer Name:David Bowie],
[Invoice Number:452172, Date:24-07-2013, Price:21458.0, Customer Name:David Beckham],
[Invoice Number:452173, Date:21-05-2017, Price:47852.0, Customer Name:David Koresh]
]
I would like to sort this list descending order of price and then by the customer name in alphabetical order in groovy.
You can use a custom sort order by passing a closure to the sort method as described here: TO THE NEW - Groovier way of sorting over multiple fields in a list of maps in groovy
list.sort { a,b ->
a.price <=> b.price ?: a.lastName <=> b.lastName
}
The "spaceship operator" (<=>) calls the compareTo method which is used for sorting. It returns 0 when both compared items are equal. This is where the elvis operator (?:) comes in: it evaluates the expression before it as boolean (according to groovy truthyness) and returns it's value if it is true. Since 0 evaluates to false, the expression behind the elvis operator is returned.
So if the price is not equal (a.price <=> b.price is not 0) the result of a.price <=> b.price is used for sorting. But if they are equal a.lastName <=> b.lastName is used for sorting.
What if you do straightforward sort?
invoices.sort { a, b ->
if (a.Price > b.Price) return -1
if (a.Price < b.Price) return 1
else
return (a.'Customer Name' > b.'CustomerName') ? -1 : 1
}

What is the purpose of question mark(?) after a variable in Groovy

I am new to grails I found in many examples that a variable may end with question mark (?)
like this
boolean equals(other) {
if(other?.is(this))
return true
}
above code contains If condition in that other is ending with a ? so I want to know the meaning of that representation
?. is a null safe operator which is used to avoid unexpected NPE.
if ( a?.b ) { .. }
is same as
if ( a != null && a.b ) { .. }
But in this case is() is already null safe, so you would not need it
other.is( this )
should be good.
There is a subtlety of ?., the Safe navigation operator, not mentioned in #dmahapatro's answer.
Let me give an example:
def T = [test: true]
def F = [test: false]
def N = null
assert T?.test == true
assert F?.test == false
assert N?.test == null // not false!
In other words, a?.b is the same as a != null && a.b only when testing for a boolean value. The difference is that the first one can either evaluate to a.b or null, while the second one can only be a.b or false. This matters if the value of the expression is passed on to another expression.

In Groovy, Is there any way to safely index into a Collection similar to the safe navigation operator?

This will safely return null without throwing any exceptions
obj?.prop1?.prop2
How can I do that for collections, where it won't throw an index out of bounds exception?
myarray[400] //how do I make it return null if myarray.size() < 400
Is there such an operator for Collections?
That's the default behavior with all collections except arrays in groovy.
assert [1,2,3,4][5] == null
def test = new ArrayList()
assert test[100] == null
assert [1:"one", 2:"two"][3] == null
If you've got an array, cast it to a list.
def realArray = new Object[4]
realArray[100] // throws exception
(realArray as List)[100] // null
You can string list and map indexes together with the ? operator in the same way as with properties:
def myList = [[name: 'foo'], [name: 'bar']]
assert myList[0]?.name == 'foo'
assert myList[1]?.name == 'bar'
assert myList[2]?.name == null
You can use get() instead:
myarray?.get(400)

Resources