I'm trying to do something that should be quite simple. I have a stream of arrays that contain 2 edges. For each array, I just want to subtract a value on the second edge from that of the first. In some languages, this would simply be array[0].value - array[1].value
. However, I've only managed to achieve this doing the following:
local(
project('a', 'b').
by(unfold().limit(1)).
by(unfold().tail(1)).
math('a - b').
by('bias'))
This works, however it seems this should be much simpler without project()
, limit()
and tail()
. It also makes me question how I would get the correct item from an array if there were 3 or more items in there. Eg. how would I get the second item if it's no longer the tail()
? I guess limit(2).tail(1)
? It just seems extremely messy. If I simple use a fold()
step, I can get extremely close to simplifying this operation:
local(
unfold().
values('bias').
fold(0, minus))
Using fold()
in this way is so clean, however results in 0 - a - b
. If I could replace that seed with a dynamic value, then I could achieve more. But even then, I would have to do something like (2 * a) - a - b
, to achieve the correct result. Attempts to replace the 0
seed with a dynamic variable such as limit(1).values('bias')
fail as it's the wrong type. But I wouldn't be satisfied with such arbitrary code anyway. Then My final thought was to index the items then select by index:
local(
index().
with(WithOptions.indexer, WithOptions.map))
While the edges are indexed fine, I can't find a way to make this useful. I thought I could select('0')
to get the first item, but nothing is returned.
I guess my question is as follows:
Is there a simple way to achieve a - b
as simply as a + b
is achieved with sum()
or fold(0, sum)
?
If not, Is there a cleaner way of choosing items in an array for maths? Or should everything generally be put in project()
before maths? It just seems so cumbersome...
You can skip project()
easy enough:
gremlin> arr = [[g.E(7).next(),g.E(8).next()],[g.E(8).next(),g.E(10).next()]]
==>[e[7][1-knows->2],e[8][1-knows->4]]
==>[e[8][1-knows->4],e[10][4-created->5]]
gremlin> g.inject(arr).unfold().as('a','b').
......1> math('a - b').
......2> by(limit(local,1).values('weight')).
......3> by(tail(local,1).values('weight'))
==>-0.5
==>0.0
You still have to unfold().limit()/tail()
but I'd say this is a better approach as it avoids creating a Map
just to throw it away.
It also makes me question how I would get the correct item from an array if there were 3 or more items in there. Eg. how would I get the second item if it's no longer the tail()? I guess limit(2).tail(1)?
You could use range()
to avoid a multi-step approach:
gremlin> arr = [[g.E(7).next(),g.E(8).next(),g.E(9).next()],[g.E(8).next(),g.E(10).next(),g.E(10).next()]]
==>[e[7][1-knows->2],e[8][1-knows->4],e[9][1-created->3]]
==>[e[8][1-knows->4],e[10][4-created->5],e[10][4-created->5]]
gremlin> g.inject(arr).unfold().as('a','b').
......1> math('a - b').
......2> by(limit(local,1).values('weight')).
......3> by(range(local,1,2).values('weight'))
==>-0.5
==>0.0
You could use sack()
to avoid math()
but I'm not sure it simplifies the picking apart of your inner list (i.e. your still stuck with limit()
/tail()
):
gremlin> arr = [[g.E(7).next(),g.E(8).next()],[g.E(8).next(),g.E(10).next()]]
==>[e[7][1-knows->2],e[8][1-knows->4]]
==>[e[8][1-knows->4],e[10][4-created->5]]
gremlin> g.withSack(0).inject(arr).unfold().
......1> sack(assign).by(limit(local,1).values('weight')).
......2> sack(minus).by(tail(local,1).values('weight')).
......3> sack()
==>-0.5
==>0.0
Good question by the way.