user10418015
user10418015

Reputation:

Xquery: find value closest to given number

I'm trying to get the ratio closes to 1, but I cannot seem to be able to find how to do it... This is my code so far:

<testadvarden> 
   {for $i in 0 to 72
   let $latitude := $i
   let $iterad := (local:distance(data($latitude)))
   return <lista latitud = "{$latitude}" ratio = "{$iterad}" /> }
</testadvarden>

My function distance only returns the ratio. These are the most relevant return values:

<testadvarden>
  <lista latitud="26" ratio="1.210681245514598"/>
  <lista latitud="27" ratio="1.1472684079724134"/>
  <lista latitud="28" ratio="1.108013683878131"/>
  <lista latitud="29" ratio="1.0367234044480529"/>
  <lista latitud="30" ratio="0.9820439101177922"/>
  <lista latitud="31" ratio="0.8714211421572755"/>
  <lista latitud="32" ratio="0.7316921947582108"/>
</testadvarden>

So my problem is how to get the given latitud for the ratio closest to 1.

Upvotes: 2

Views: 99

Answers (1)

Martin Honnen
Martin Honnen

Reputation: 167706

Would a sort on abs(1 - @ratio) give the closest one?

You could further process your lista elements with e.g.

for $l in */lista
order by abs(1 - $l/@ratio) ascending
count $pos
where $pos = 1
return data($l/@latitud)

At https://xqueryfiddle.liberty-development.net/b4GWVa that returns 30. Instead of using count/where to identify the first/closest item in the sorted sequence you could also use head:

head(
  for $l in */lista
  order by abs(1 - $l/@ratio) ascending
  return $l
)/@latitud/data()

Instead of using order by to sort, in XQuery 3.1 with higher order/inline functions you could also use the sort function with e.g.

data(head(sort(lista, (), function($l) { abs(1 - $l/@ratio) }))/@latitud)

complete sample would be

declare context item := <testadvarden>
  <lista latitud="26" ratio="1.210681245514598"/>
  <lista latitud="27" ratio="1.1472684079724134"/>
  <lista latitud="28" ratio="1.108013683878131"/>
  <lista latitud="29" ratio="1.0367234044480529"/>
  <lista latitud="30" ratio="0.9820439101177922"/>
  <lista latitud="31" ratio="0.8714211421572755"/>
  <lista latitud="32" ratio="0.7316921947582108"/>
</testadvarden>;

data(head(sort(lista, (), function($l) { abs(1 - $l/@ratio) }))/@latitud)

Upvotes: 2

Related Questions