Closed bryant-bolyen closed 4 years ago
@Bryant-LettucePrime I'm taking a look right now before the Pittsburgh DH presentations at 10...Before looking at your code, though, I will say that avg()
will do what you ask as long as you can output the entire sequence of all the values across your five directories (your collection of collections).
Yeah, if I knew how to step out of a for loop it would make this trivial.
@Bryant-LettucePrime Preliminary thoughts, looking at your code. Do I understand this correctly? You're looking for a count of all the elements marked song by song (in your loop over the titles), and then you want to determine the average of those counts per album, right?
If I'm right about this, you'll want to store some values in variables. For each album, you need an average of the sequence of counts per each song. So, first of all, you need a variable that will collect a sequence of all the counts coming in for each song. For this, I think we'll do something kind of meta: We'll want to define a variable that stores the return of a FLWOR.
Once you have that that sequence, in a for-loop over the albums, you'll be able to apply avg
to return 5 average values (one per each album). This is a little advanced, and I'm happy to help you with it...It'll have to wait until the noon hour, though as I'm tuning into the Pgh presentations now and have a class at 11.
@Bryant-LettucePrime Preliminary thoughts, looking at your code. Do I understand this correctly? You're looking for a count of all the elements marked song by song (in your loop over the titles), and then you want to determine the average of those counts per album, right?
If I'm right about this, you'll want to store some values in variables. For each album, you need an average of the sequence of counts per each song. So, first of all, you need a variable that will collect a sequence of all the counts coming in for each song. For this, I think we'll do something kind of meta: We'll want to define a variable that stores the return of a FLWOR.
Once you have that that sequence, in a for-loop over the albums, you'll be able to apply
avg
to return 5 average values (one per each album). This is a little advanced, and I'm happy to help you with it...It'll have to wait until the noon hour, though as I'm tuning into the Pgh presentations now and have a class at 11.
Sounds good! Thanks!
@Bryant-LettucePrime Got you started, I think! I saved this is in a new file instead of writing overtop of yours: It's here in the database: /db//bab184/projectTesting-ebb.xql
But here is the whole file. Notice the variable that is set up in your for-loop over the 5 albums: That one variable, $albumCounts
, contains the return of a FLWOR:
xquery version "3.1";
(:The goal of this XPath is to count XML elements from multiple directories and output the average value from each directory:)
let $discog := collection('/db/brandnew/XML/Albums')
let $albumRef := $discog//album/@ref/string() ! normalize-space()
let $albumDist := $albumRef => distinct-values()
(: Target title @ref from album @ref :)
for $albumIndex in $albumDist
let $titleRef := $discog//title[following-sibling::album/@ref = $albumIndex]/@ref/string() ! normalize-space()
let $titleDist := $titleRef => distinct-values()
(: Put this all in the right order :)
order by $albumIndex
(: Initialize variable for a cumulative sum of count in the next structure:)
let $partAddend := number('0')
let $albumCounts :=
(: Target count from title and album @refs :)
for $titleIndex in $titleDist
let $partRef := $discog//song[preceding::album/@ref = $albumIndex][preceding::title/@ref = $titleIndex]/(child::intro | prelude | interlude| postlude | verse | chorus | bridge | outro | preChorus | instrumental) ! name()
let $partCount := $partRef=> count()
(:Now that we have the values, is it possible to take the average of the collection? The avg() function won't return values we want because it operates on the current index of the loop and would be redundant. Below I have an algorithm for getting a running total, but its output renders it redundant as well. It seems as though partAddend isn't staying initialized to the sum and may be returning to zero, but albumIndex shouldn't be iterating until titleIndex has finished a full revolution? Maybe there's a bug in my loops that could also be causing this.:)
let $partSum := sum(($partCount, $partAddend))
let $partAddend := $partSum
return $partSum
return concat($albumIndex, ': ', (string-join($albumCounts, ', ')))
@Bryant-LettucePrime Run this to view the return. And I leave it to you to apply the avg()
function at this point. But I think this gets you what you need...
@ebeshero AHA! So declaring complex variables like this allows a programmer to nest results, terminating a for loop and iterate on the output. This was the missing piece in the puzzle. I'll do some shenaniganry to make an SVG we can use.
Thanks!
@Bryant-LettucePrime Yes indeed! Happy graphing! :-D
I'm trying to get a count of specific XML entities across five directories and output the average value for each directory.
My code can be found on eXist at: /db/bab184/projectTesting
We step through a loop to retrieve
Lines 18 - 32 are the most important (seen here):
P.S. don't judge that ugly drop into the child axis it works ok
@ebeshero @alnopa9 @frabbitry @BMT45