Arangodb: How to use MERGE_RECURSIVE() With an Array - arangodb

In AQL, the MERGE_RECURSIVE function cannot take an array as an input. How then would I use said function with the result of a previous query, which is, of course, an array?
For example, if the output of my query result is:
[
{
"John": {"city": "Berlin"}
},
{
"John": {"country": "Germany"}
}
]
I want to MERGE_RECURSIVE(myResult) to return:
{
"John": {"city": "Berlin", "country": "Germany"}
}
I just need a way to use MERGE_RECURSIVE with my query's output array

If you got an array like x = [1, 2, 3] but the function you want to pass this to requires each element as separate argument, so SOME_FUNC(1, 2, 3) instead of SOME_FUNC( [1, 2, 3] ), then there's the APPLY() function to spread the array:
APPLY("SOME_FUNC", [1, 2, 3] )
This is essentially like the following call:
SOME_FUNC(x[0], x[1], x[2])
... but you spare yourself to type all that with APPLY() and it will work with a variable number of elements in the array. So the solution in your case is:
RETURN APPLY("MERGE_RECURSIVE", myResult)

Related

Count duplicate string occurances in Terraform list

I am struggling with seemingly simple task in Terraform. I would easily do it with Ruby/Python with local variable inside the for loop, but Terraform doesn't have those.
Here is an issue.
I have a list with multiple duplicate string occurances:
list = ["a","b","c","a","b","c","a"]
I want to count how many times the same string occured from the beginning, but keep the count in the same location, so the resulting list would become this:
index_list = [1, 1, 1, 2, 2, 2, 3]
Is it possible with Terraform?
We can do the following:
locals {
lst = ["a", "b", "c", "a", "b", "c", "a"]
index_list = [for index, item in local.lst : length([for i in slice(local.lst, 0, index + 1) : i if i == item])]
}
output "index_list" {
value = local.index_list
}
Output for index_list:
index_list = [
1,
1,
1,
2,
2,
2,
3,
]
The first for loop iterates through the list. The second for loop is a slice combined with a filter. The slice function creates a sublist from the first element to the index if the current element. With the filter (if i == item) we filter out from this sublist all the elements which are equal to the current element. Last but not least, we get the length of this filtered list.

What is the difference between any and find in groovy?

I am trying to get the set values from closure in groovy:
myList(1, 2, 3).any { it > 2 }
myList(1, 2, 3).find { it > 2 }
So not able to figure out, which one to use and better.
any returns boolean - true if any of the elements on the list matches the closure condition, while find returns first element that meets the criteria in closure being passed.
If you need to know if there're elements matching certain criteria, use any, if you need only a single element (the first one) use, find, if you need all the elements that matches the closure passed use findAll.
Example:
assert [1, 2, 3].any { it > 1 }
assert [1, 2, 3].find { it > 1 } == 2
assert [1, 2, 3].findAll { it > 1 } == [2, 3]

Underscore GroupBy Sort

I have a question regarding programming in function style.
I use underscore.js library.
Let's consider some use-case. I have an array of some labels with repetitions I need to count how many occurrences of each label is in array and sort it according to the number of occurrences.
For counting, how many labels I can use countBy
_.countBy([1, 2, 3, 4, 5], function(num) {
return num % 2 == 0 ? 'even': 'odd';
});
=> {odd: 3, even: 2}
But here, as result I have a hash, which doesn't have meaning for order, so there is no sort. So here, I need to convert the hash to array then to sort it and convert backward to hash.
I am pretty sure there is an elegant way to do so, however I am not aware of it.
I would appreciate any help.
sort it and convert backward to hash.
No, that would loose the order again.
You could use
var occurences = _.countBy([1, 2, 3, 4, 5], function(num) {
return num % 2 == 0 ? 'even': 'odd';
});
// {odd: 3, even: 2}
var order = _.sortBy(_.keys(occurences), function(k){return occurences[k];})
// ["even", "odd"]
or maybe just
_.sortBy(_.pairs(occurences), 1)
// [["even", 2], ["odd", 3]]

How to get all elements from a list without the last element?

The following Groovy code
lines = ['0','1','2','3','4','5']
println lines[1..lines.size()-1]
println lines[1..-1]
println lines[1..<lines.size()-1]
println lines[1..<-1]
println lines[1..<-2]
println lines[1..-2]
produces this output:
[1, 2, 3, 4, 5]
[1, 2, 3, 4, 5]
[1, 2, 3, 4]
[1, 0]
[1, 2, 3, 4, 5]
[1, 2, 3, 4]
Since -1 is the index of the last element in the list, the first two make sense (ranges in Groovy include the end element instead of omitting it as everywhere else in Java :-( )
Line #3 is the desired output (list without first and last element).
I'm worried about the output #4: Why do I get [1, 0] for 1..-1?
Also [1, 2, 3, 4, 5] for the range 1..<-2 seems wrong.
Why does that happen?
The best way to take all elements but the last one, in my opinion, is to use the take method:
def list = ['a', 'b', 'c']
assert list.take(list.size() - 1) == ['a', 'b']
It behaves properly in the corner case where size == 1:
def list = ['one']
assert list.take(list.size() - 1) == []
Though I'd prefer it to throw an exception in the case size == 0, but the behavior is not that bad:
def list = []
assert list.take(list.size() - 1) == []
You can also use list[0..<list.size()-1] (your third example) and it will behave the same except for the empty list, in which case it will throw an ArrayIndexOutOfBoundsException, but i think is not as readable as the take counterpart.
Another acceptable solution is using list[0..-2] (your last example), which i think looks much more elegant, but unfortunately breaks when size == 1 with an ArrayIndexOutOfBoundsException.
In your examples (i'll assume that you meant to use 0 as the starting index instead of 1 if you wanted to include all elements but the last one):
lines[0..lines.size()-1] is equivalent to lines[0..-1] because the getAt(Range) method of lists will treat ranges with negative indexes the same way asgetAt(Integer) does, i.e. as accessing the (list.size() + negativeIndex)'th element of the list. Therefore list[0..-1] is the same as saying "from first element to last" and it's the same as copying the list; and list[-1..0] is the same as "from last to first" and it's equivalent to list.reverse() :)
The problem with the other non-inclusive range example is that the non-inclusive ranges are being evaluated before the list access and they evaluate to an incorrect inclusive range. For example, 0..<-2 evaluates to 0..-1, and that's why it's returning all the elements. 0..<-1 evaluates to 0..0 and it returns only the first element.
Notice that the empty range is a special case. It's denoted as 0..<0 and it doesn't have an inclusive equivalent (so Groovy won't do any magic conversion here). And that's why list[0..<list.size()-1] works when size == 1 (the range evaluates to the empty range) while list[0..-2] doesn't :)
Maybe this has changed since epideman wrote his answer, but you can get the whole list without the last element with 0..<-1:
assert ["foo"][0..<-1] == []
assert ["foo", "bar"][0..<-1] == ["foo"]
assert ["foo", "bar", "baz"][0..<-1] == ["foo", "bar"]
// blows up if empty, here take is better
assert [][0..<-1] == [] // BOOM
// if you want null safe, use take
assert [].take(-1) == []
This is with groovy 2.2.1.
Since Groovy 2.4 you can use the init() method:
lines = ['0','1','2','3','4','5']
assert lines.init() == ['0','1','2','3','4']

Groovy - Get first elements in multi-dimensional array

I have a groovy list of lists i.e.
list = [[2, 0, 1], [1, 5, 2], [1, 0, 3]]
I would like to get a subset of just the first elements of each array
sublist = [2, 1, 1]
I know I can loop through the and just get the first element and add, but I am trying to avoid this since I have a huge array of values. I'm trying to avoid this solution
def sublist = []
list.each {
sublist.add(it[0])
}
Thanks.
A more readable version:
list*.first()
You could try:
list.collect { it[0] }
Although that still involves iteration (although somewhat hidden). However, it's likely that any solution is going to involve iteration somewhere down the line, whether it be written by you or the library/API method you call.
If you're worried about copying the data, a better approach might be to create a custom iterator, rather than copying the data into another list. This is a great approach if you only need to traverse through the sublist once. Also, if you don't traverse to the end of the sublist, you haven't wasted any effort on the elements you never processed. For example:
bigList = [[2, 0, 1], [1, 5, 2], [1, 0, 3]]
bigListIter = bigList.iterator()
firstOnlyIter = [
hasNext: { -> bigListIter.hasNext() },
next: { -> bigListIter.next().first() }
] as Iterator
for (it in firstOnlyIter) {
println it
}
You can always turn the iterator back into a list with Iterator.toList().

Resources