Это решение может приблизить вас к тому, что вам нужно, хотя я не уверен, что оно точно подходит, поскольку оно позволяет вам вычислять среднее значение только на выбранном уровне иерархии (то есть на «A» или «A1»). Вот мой сеанс Гремлина:
gremlin> g = new TinkerGraph()
==>tinkergraph[vertices:0 edges:0]
gremlin> a = g.addVertex("a")
==>v[a]
gremlin> a1 = g.addVertex("a1")
==>v[a1]
gremlin> a2 = g.addVertex("a2")
==>v[a2]
gremlin> a.addEdge('has',a1)
==>e[0][a-has->a1]
gremlin> a.addEdge('has',a2)
==>e[1][a-has->a2]
gremlin> a1.addEdge('relationship',g.addVertex("a11",[points:20]))
==>e[2][a1-relationship->a11]
gremlin> a1.addEdge('relationship',g.addVertex("a12",[points:20]))
==>e[3][a1-relationship->a12]
gremlin> a2.addEdge('relationship',g.addVertex("a21",[points:100]))
==>e[4][a2-relationship->a21]
gremlin> a2.addEdge('relationship',g.addVertex("a22",[points:0]))
==>e[5][a2-relationship->a22]
gremlin> p=g.v("a").out.loop(1){it.loops<10}{true}.path.filter{it.last().getProperty("points")!=null}.toList()
==>[v[a], v[a2], v[a22]]
==>[v[a], v[a2], v[a21]]
==>[v[a], v[a1], v[a12]]
==>[v[a], v[a1], v[a11]]
gremlin> p.collect{[it, it.last().getProperty("points")]}._().groupBy{it[0][0]}{it[1]}{it.sum()/it.size()}.cap.next()
==>v[a]=35
gremlin> p.collect{[it, it.last().getProperty("points")]}._().groupBy{it[0][1]}{it[1]}{it.sum()/it.size()}.cap.next()
==>v[a1]=20
==>v[a2]=50
Итак, эта строка дает нам пути, которые имеют значение (т.е. те, которые заканчиваются листовым узлом, имеющим points
:
p=g.v("a").out.loop(1){it.loops<10}{true}.path.filter{it.last().getProperty("points")!=null}.toList()
Я сохраняю их в p
для дальнейшего использования. Обратите внимание, что это будет исследовать дерево на глубину 10, как это контролируется it.loops<10
. Отсюда довольно просто использовать p
для вычисления средних значений. Вот пример его расчета для A:
p.collect{[it, it.last().getProperty("points")]}._().groupBy{it[0][0]}{it[1]}{it.sum()/it.size()}.cap.next()
Вышеупомянутое в основном говорит, что для каждого пути преобразуйте его в новый список, где первый элемент - это путь, а второй элемент - это точки в листовом узле. Преобразуйте этот список в конвейер с функцией идентификации и сгруппируйте по первому элементу пути (обозначенному it[0][0]
) и возьмите значение точек (второе замыкание на groupBy
) для этого пути. Третье замыкание на groupBy
- это функция-редуктор, которая суммирует баллы и вычисляет на их основе среднее значение.
Другой альтернативой, если вам нужно рассчитать только среднее значение для одной вершины, был бы такой подход:
gremlin> g.v("a").out.loop(1){it.loops<10}{true}.path{it.points}.filter{it.last()!=null}
.transform{it.last()}.gather.transform{it.sum()/it.size()}
==>35
Обратите внимание, что обход в основном такой же в начале, но использует закрытие при захвате пути. Это замыкание преобразует вершину в значение свойства points
(обратите внимание, что использование it.getProperty("points")
намного эффективнее, чем it.points
). Оттуда я снова отфильтровываю пути, которые имеют нулевое значение, последний элемент в пути (т.е. поскольку листовые узлы являются единственными, у которых есть свойство точек, это должно оставить нам пути, которые заканчиваются листьями). Затем я преобразовываю эти пути, чтобы получить точки, собрать их в список и преобразовать список в средние точки для «А».
person
stephen mallette
schedule
29.01.2014