How to find sum of all descendents attribute named x in ArangoDB? - arangodb

As i have tree structure in my graph database ArangoDB like below
The node with id 2699394 is a parent node of this graph tree. and each node has attribute named X assigned to it. I want to know sum of x of all the descendants of parent node 2699394 exclusive of its own attribute x in sum.
for example suppose if,
2699399 x value is = 5,
2699408 x value is = 3,
2699428 x value is = 2,
2699418 x value is = 5,
then parent node 2699394 sum of x should be = 5 + 3 + 2 + 5
= 15
so the answer is 15. So can anybody give me query for this calculation in ArangoDB AQL?
To find out no of descendants of particular node, i have used below query,
`FOR v, e, p in 1..1000 OUTBOUND 'Person/1648954'
GRAPH 'Appes'
RETURN v.id`
Thanks in Advance.
Mayank

Assuming that children are linked to their parents, the data could be visualized like this:
nodes/2699394 SUM of children?
↑
nodes/2699399 {x: 5}
↑
nodes/2699408 {x: 3}
↑
nodes/2699428 {x: 2}
↑
nodes/2699418 {x: 5}
To walk the chain of children, we need to traverse in INBOUND direction (or OUTOBUND if parent nodes point to children):
FOR v IN 1..10 INBOUND "nodes/2699394" relations
RETURN v
In this example, an anonymous graph is used by specifying an edge collection relations. You can also use a named graph, like GRAPH "yourGraph".
Starting at nodes/2699394, the edges down to nodes/2699418 are traversed and every node on the way is returned unchanged so far.
Since we are only interested in the x attribute, we can change that to only return that attribute: RETURN v.x - which will return [ 5, 3, 2, 5 ]. Unless we say IN 0..10, the start vertex will not be included.
Inside the FOR loop, we don't have access to all the x values, but only one at a time. We can't do something like RETURN SUM(v.x) here. Instead, we need to assign the result of the traversal to a variable, which makes it a sub-query. We can then add up all the numbers and return the resulting value:
LET x = (
FOR v IN 1..10 INBOUND "nodes/2699394" relations
RETURN v.x
)
RETURN SUM(x) // [ 15 ]
If you want to return the start node with a computed x attribute, you may do the following:
LET doc = DOCUMENT("nodes/2699394")
LET x = (
FOR v IN 1..10 INBOUND doc relations
RETURN v.x
)
RETURN MERGE( doc, { x: SUM(x) } )
The result will be like:
[
{
"_id": "nodes/2699394",
"_key": "2699394",
"_rev": "2699394",
"x": 15
}
]

Related

run time exceeded on all test cases : Ideas how to optimize this code?

It runs fine for small sets of input, but with very large input it runs more than one second. Looking for ideas to optimize execution time. This is a codesignal challenge, I already submitted, but could not optimize and still curious.
Any ideas are appreciated to help optimize this code; Seems most things I've tried have affected the results, so here is the clean code that works.
Here is the description:
You've created a new programming language, and now you've decided to add hashmap support to it. Actually you are quite disappointed that in common programming languages it's impossible to add a number to all hashmap keys, or all its values. So you've decided to take matters into your own hands and implement your own hashmap in your new language that has the following operations:
• insert x y - insert an object with key x and value y.
• get x - return the value of an object with key x.
• addToKey x - add x to all keys in map.
• addToValue y - add y to all values in map.
To test out your new hashmap, you have a list of queries in the form of two arrays: queryTypes contains the names of the methods to be called (eg: insert, get, etc), and queries contains the arguments for those methods (the x and y values).
Your task is to implement this hashmap, apply the given queries, and to find the sum of all the results for get operations.
#For queryType = ["insert", "insert", "addToValue", "addToKey", "get"]
#and query = [[1, 2], [2, 3], [2], [1], [3]], the output should be solution
#(queryType, query) = 5.
#The hashmap looks like this after each query:
#1 query: {1: 2}
#2 query: {1: 2, 2: 3}
#3 query: {1: 4, 2: 5}
#4 query: {2: 4, 3: 5}
#5 query: answer is 5
from collections import defaultdict
def solution(queryType, query):
hashmap = defaultdict(int)
results = []
updated_keys = set()
def insert(key, value):
hashmap[key] = value
def get(key):
results.append(hashmap[key])
def add_to_key(val):
updated_dict = {}
for key, value in hashmap.items():
updated_key = key + val
updated_dict[updated_key] = value
hashmap.clear()
hashmap.update(updated_dict)
def add_to_value(val):
nonlocal hashmap
hashmap = {k: v + val for k, v in hashmap.items()}
for i in range(len(queryType)):
op = queryType[i]
q = query[i]
if op == "insert":
insert(*q)
elif op == "get":
get(q[0])
elif op == "addToKey":
add_to_key(q[0])
elif op == "addToValue":
add_to_value(q[0])
return sum(results)

Conditionally use parts of a nested for loop

I've searched for this answer extensively, but can't seem to find an answer. Therefore, for the first time, I am posting a question here.
I have a function that uses many parameters to perform a calculation. Based on user input, I want to iterate through possible values for some (or all) of the parameters. If I wanted to iterate through all of the parameters, I might do something like this:
for i in range(low1,high1):
for j in range(low2,high2):
for k in range(low3,high3):
for m in range(low4,high4):
doFunction(i, j, k, m)
If I only wanted to iterate the 1st and 4th parameter, I might do this:
for i in range(low1,high1):
for m in range(low4,high4):
doFunction(i, user_input_j, user_input_k, m)
My actual code has almost 15 nested for-loops with 15 different parameters - each of which could be iterable (or not). So, it isn't scalable for me to use what I have and code a unique block of for-loops for each combination of a parameter being iterable or not. If I did that, I'd have 2^15 different blocks of code.
I could do something like this:
if use_static_j == True:
low2 = -999
high2 = -1000
for i in range(low1,high1):
for j in range(low2,high2):
for k in range(low3,high3):
for m in range(low4,high4):
j1 = j if use_static_j==False else user_input_j
doFunction(i, j1, k, m)
I'd just like to know if there is a better way. Perhaps using filter(), map(), or list comprehension... (which I don't have a clear enough understanding of yet)
As suggested in the comments, you could build an array of the parameters and then call the function with each of the values in the array. The easiest way to build the array is using recursion over a list defining the ranges for each parameter. In this code I've assumed a list of tuples consisting of start, stop and scale parameters (so for example the third element in the list produces [3, 2.8, 2.6, 2.4, 2.2]). To use a static value you would use a tuple (static, static+1, 1).
def build_param_array(ranges):
r = ranges[0]
if len(ranges) == 1:
return [[p * r[2]] for p in range(r[0], r[1], -1 if r[1] < r[0] else 1)]
res = []
for p in range(r[0], r[1], -1 if r[1] < r[0] else 1):
pa = build_param_array(ranges[1:])
for a in pa:
res.append([p * r[2]] + a)
return res
# range = (start, stop, scale)
ranges = [(1, 5, 1),
(0, 10, .1),
(15, 10, .2)
]
params = build_param_array(ranges)
for p in params:
doFunction(*p)

Pick elements on (un)even index from an array in Groovy

I have a Groovy array containing digits of a number. I need to create two new arrays containing only the digits at even resp. uneven positions from that array.
The best way that I could find is this, but I feel there's quite a lot of room for improvement here:
def evenDigits = digits
.indexed(1)
.findAll { i, v -> i % 2 == 0 }
.collect { it.value }
Obviously the unevenDigits variant would be to simply check the modulus in the findAll closure against 1 instead of 0.
Does anyone know if this code can be improved or compacted?
A "less smarter" (and definitely more performant) solution:
def evens = [], odds = []
digits.eachWithIndex{ v, ix -> ( ix & 1 ? odds : evens ) << v }
You can use groupBy to separate the results to odd/even items. E.g.
groovy:000> ["a","b","c"].indexed(1).groupBy{ i, _ -> i & 1 }.collectEntries{ k, v -> [k as Boolean, v.values()] }
===> [true:[a, c], false:[b]]
One more "Groovy" solution that uses withIndex() and findResults() combination.
withIndex() transforms a List<T> to List<Tuple2<T,Integer>> - a list of value-index tuples.
findResults(closure) runs filtering transformation - the closure it receives is a transforming predicate. In our case, it checks if the index value is odd or even and extracts the value from tuple if the predicate matches. (All null values are filtered out.)
Short and concise. Requires a minimal number of transformations: List<T> to List<Tuple2<T,Integer>> and then a single iteration to produce the final result.
def numbers = [1,2,3,4,5,6,2,3,1] // Some test data
def even = { t -> t.second % 2 == 0 ? t.first : null } // "Even" transforming predicate
def odd = { t -> t.second % 2 == 1 ? t.first : null } // "Odd" transforming predicate
def evens = numbers.withIndex(1).findResults even
def odds = numbers.withIndex(1).findResults odd
// And some assertions to test the implementation
assert evens == [2,4,6,3]
assert odds == [1,3,5,2,1]
Another option, for a single pass (but still with the intermediate collection due to indexed), would be a reduce:
def (odd,even) = digits.indexed().inject([[],[]]){ acc, it -> acc[it.key&1] << it.value; acc }
I came up with this, but it's probably not the cleverest way.
def isEven = { int x -> x % 2 == 0 ? x : null}
def (digits, evens, odds) = [[1, 2, 3, 4, 5, 6, 7, 8, 9], [], []]
digits.each {
if (isEven(it))
evens.add(isEven(it))
}
odds = digits - evens
assert evens == [2, 4, 6, 8]
assert odds == [1, 3, 5, 7, 9]

NodeJs Underscore sortby

i need to sort an array by its x value:
before sort
arr=>
[
{x:0, y: 1234},
{x:3, y: 324},
{x:1, y: 3487},
]
after sort:
arr =>
[
{x:0, y: 1234},
{x:1, y: 3487},
{x:3, y: 324},
]
and I m using NodeJs and CoffeeScript, I tried to use the Underscore's sortBy, but it won't work:
_.sortBy(arr, (x) -> arr.x)
Try:
_.sortBy(arr, (item) -> item.x)
The second arg to sortBy is just a function that maps an item on the collection to the value you want to sort on. In this case the item on the collection is one of the objects in your array e.g. {x:0, y: 1234}. So you just need to pick the x property as the value to sort by.
From the fine manual:
sortBy _.sortBy(list, iterator, [context])
Returns a (stably) sorted copy of list, ranked in ascending order by the results of running each value through iterator. Iterator may also be the string name of the property to sort by (eg. length).
Note the last sentence. That means that there is a shortcut for the common case you're facing:
sorted = _(arr).sortBy('x')

Collect only if result is not null

I have a collection and I'm wanting to find certain elements and transform them. I can do this in two closures but I was wondering if it is possible with only one?
def c = [1, 2, 3, 4]
def result = c.findAll {
it % 2 == 0
}
result = result.collect {
it /= 2
}
My true use case is with Gradle, I want to find a specific bunch of files and transform them to their fully-qualified package name.
You can use findResults:
def c = [1, 2, 3, 4]
c.findResults { i ->
i % 2 == 0 ? // if this is true
i / 2 : // return this
null // otherwise skip this one
}
Also, you will get [] in case none of the elements satisfies the criteria (closure)

Resources