Как сравнивать значения в разных объектах jq - PullRequest
2 голосов
/ 05 апреля 2020

JSON:

{"blockHistory":[10, 12, 14, 17],
"hashrateHistory":[
{"hr":1,"time":9},
{"hr":2,"time":10},
{"hr":3,"time":11},
{"hr":4,"time":12},
{"hr":5,"time":13},
{"hr":6,"time":14},
{"hr":7,"time":15}
]

Я хочу получить hr для каждого значения из blockHistory, где время из hashrateHistory является наибольшим временем <= blockHistory. </p>

Это то, что у меня есть , Я не знаю, как получить lastHR

 [{lastHr: .hashrateHistory[].hr, time: .blockHistory[]}] | sort_by(.time)

результат, который я хочу:

[
  {
    "lastHr": 2,
    "time": 10
  },
  {
    "lastHr": 4,
    "time": 12
  },
  {
    "lastHr": 6,
    "time": 14
  },
  {
    "lastHr": 7,
    "time": 17
  }

]

Ответы [ 3 ]

1 голос
/ 05 апреля 2020

Вот еще один подход, который использует group_by после создания промежуточного результата

  .blockHistory as $b
| [ .hashrateHistory[] | .group = [ $b[] < .time ] ] 
| group_by(.group) 
| map(max_by(.time) | del(.group)) 
| sort_by(.time)

На основании вашей первоначальной попытки это включает в себя окончательный sort_by, но это может быть необязательно.

Попробуйте онлайн!

1 голос
/ 06 апреля 2020

Вот решение, ориентированное на экономию времени, в предположении, что массив .blockHistory достаточно большой и «интересный», чтобы компенсировать авансовые инвестиции в создание словаря ($ dict) и сортировку .hashrateHistory. array by .time.

Случай точного совпадения обрабатывается с помощью словаря ($ dict), а другой случай обрабатывается с помощью встроенной функции bsearch для проведения двоичного поиска:

.hashrateHistory as $hashrateHistory
| INDEX($hashrateHistory[]; .time) as $dict
| ($hashrateHistory | sort_by(.time) ) as $sorted
| ($sorted | map(.time)) as $sorted_time
| ($sorted | map(.hr)) as $sorted_hr
| .blockHistory
| map( . as $t
       | $dict[$t|tostring]
       | if . then {lastHr: .hr, time }
         else (-2 - ($sorted_time | bsearch($t))) as $i
         | {lastHr: $sorted_hr[$i], time: $t}
         end )

1 голос
/ 05 апреля 2020
(.hashrateHistory | sort_by(.time)) as $hashrate
| .blockHistory | map(
    . as $max_time
    | $hashrate
    | map(select(.time <= $max_time))[-1]
    | {lastHr: .hr, time: $max_time}
)

Для каждого элемента блока итерируйте отсортированный / сохраненный хэшрейт. Выберите только последний соответствующий элемент и создайте объект на карте блока.

...