Page 1 of 1

sort within a sort

Posted: 02 Sep 2019 12:51
by Ron Melby

Code: Select all

                                                                                                                                                                                             
SIBLEY, Joseph Charles Jr.      M (1845 - 1911)  24 Oct 1861 Civil War(18611024)              US Army             Musician          Company G 3rd MN Infantry                                          
                                                        1862 Civil War(18620000)              US Army                               1st MN Cavalry                                                     
                                                             Civil War('')                                                    Courts Martial                                                     
                                                             Civil War  ('')                                                  War Records                                                        
                                                  2 Sep 1865 Civil War(18650902)                                                    mustered out                                                       
                                                  1 Jan 1864 Civil War(18640101)           US Army             Veteran Volunteer Company G 3rd MN Infantry                                          
                                                    aft 1865           (18651231)                                                   Member of the Grand Army of the Republic                           
                                                                                                                                                                                             

this is a chunk of my report, the characters in parenthesis are one of the fields it is sorted on(verified these are the fields)


table.sort(GEDRCD, function(a, b) return a.WAR < b.WAR end)
table.sort(GEDRCD, function(a, b) return a.SDFSVC < b.SDFSVC end)
table.sort(GEDRCD, function(a, b) return a.NAME < b.NAME end)

GEDRCD contains all my fields from the various mat functions)
SDFSVC is built using *XTYPE and *XDATE1 and a lot of code, and I mean a lot, some from the internet. as I said SDFSVC in parens is verified. d

how can I sort date WITHIN name?

Re: sort within a sort

Posted: 02 Sep 2019 14:02
by tatewise
Give us some clues Ron.
What table structures are involved in GEDRCD and what I assume are sub-tables WAR and SDFSVC ?
If you don't supply the data structures, how can we possibly explain how to sort them?

Have you debugged function(a, b) return a.SDFSVC < b.SDFSVC end the same as before with a separate function?
Remember sorting usually only works on text.

Re: sort within a sort

Posted: 02 Sep 2019 14:50
by Ron Melby
turns out the problem lies elsewhere and is rather arcane:

001 1 _ATTR Civil War, US Army, 1LT, Infantry
002 2 TYPE MILT
003 2 DATE 15 FEB 1864

004 1 _ATTR Civil War, US Army, CPT, Company I 24th WI Infantry Volunteers
005 2 TYPE MILT
006 2 DATE BEF 13 MAR 1865

007 1 _ATTR Civil War, US Army, BVT MAJ, USA Volunteers
008 2 TYPE MILT
009 2 DATE 13 MAR 1865

010 1 _ATTR Civil War, US Army, , Mustered out of Company I 24th Regiment Infantry
011 2 TYPE MILT
012 2 DATE 10 JUN 1865

when I enter the routine dptr is pointing at rcd 1, 4, 7, 10 respectively
parse(xd) not at issue...yet

local xtyp = fhGetItemText(dptr, '~.DATE:XDATETYPE')

if xtyp == 'After' then
xdat = fhGetItemText(dptr, '~.DATE:XDATE1')
xd = parse(xdat)
dsf = bldseg(xtyp, xd)
return dsf
end

if xtyp == 'Approx' then
xdat = fhGetItemText(dptr, '~.DATE:XDATE1')
xd = parse(xdat)
dsf = bldseg(xtyp, xd)
return dsf
end

if xtyp == 'Before' then
**** xdat = fhGetItemText(dptr, '~.DATE:XDATE1')
xd = parse(xdat)
dsf = bldseg(xtyp, xd)
return dsf
end

if xtyp == 'Between' then
xdat = fhGetItemText(dptr, '~.DATE:XDATE1')
xd = parse(xdat)
ytyp = 'From'
dsf = bldseg(ytyp, xd)
return dsf
end

if xtyp == 'Date' then
year = fhGetItemText(dptr, '~.DATE:YEAR')
month = fhGetItemText(dptr, '~.DATE:MONTH_NUMBER')
day = fhGetItemText(dptr, '~.DATE:DAY')
if month > '' then
month = zpdat(month)
else
month = '07'
end
if day > '' then
day = zpdat(day)
else
day = '01'
end
dsf = (year or '') .. (month or '') .. (day or '')
return dsf
end

if xtyp == 'From/To' then
xdat = fhGetItemText(dptr, '~.DATE:XDATE1')
xd = parse(xdat)
ytyp = 'From'
dsf = bldseg(ytyp, xd)
return dsf
end

-- no date exists
dsf = ''
return dsf
end -- fn crtDSF

dptr is pointing at record 4, and I expect the offset to put me in record 6.
xdatetype == 'Before'
**** at the execution of that statement, xdat == ''

this is -- to understate the fact, massively unexpected. And this is not the case for many of the other records I have debugged, in this **** area.

this is the table segment result:

[156] => (table .16)
AGE => 83
RLT => " 1st cousin (x06) removed"
NAME => "SIBLEY, William H. "
RANK => " CPT"
DSFSVC => "0000"
pINDI (item) => Individual: William H. SIBLEY
ARM => " US Army"
WAR => "Civil War"
RCDID => 2017
OTH => " Company I 24th WI Infantry Volunteers"
SORT => "111847"
DRM => "ff"
SVCDAT => "bef 1865"
pATTR (item) => MilSvc: Civil War, US Army, CPT, Company I 24th WI Infantry Volunteers
DATES => "(1847 - 1930)"
SEX => "M"

[157] => (table .16)
AGE => 83
RLT => " 1st cousin (x06) removed"
NAME => "SIBLEY, William H. "
RANK => " 1LT"
DSFSVC => "18640215"
pINDI (item) => Individual: William H. SIBLEY
ARM => " US Army"
WAR => "Civil War"
RCDID => 2017
OTH => " Infantry"
SORT => "111847"
DRM => "ff"
SVCDAT => "15 Feb 1864"
pATTR (item) => MilSvc: Civil War, US Army, 1LT, Infantry
DATES => "(1847 - 1930)"
SEX => "M"

[158] => (table .16)
AGE => 83
RLT => " 1st cousin (x06) removed"
NAME => "SIBLEY, William H. "
RANK => " BVT MAJ"
DSFSVC => "18650313"
pINDI (item) => Individual: William H. SIBLEY
ARM => " US Army"
WAR => "Civil War"
RCDID => 2017
OTH => " USA Volunteers"
SORT => "111847"
DRM => "ff"
SVCDAT => "13 Mar 1865"
pATTR (item) => MilSvc: Civil War, US Army, BVT MAJ, USA Volunteers
DATES => "(1847 - 1930)"
SEX => "M"

[159] => (table .16)
AGE => 83
RLT => " 1st cousin (x06) removed"
NAME => "SIBLEY, William H. "
RANK => " "
DSFSVC => "18650610"
pINDI (item) => Individual: William H. SIBLEY
ARM => " US Army"
WAR => "Civil War"
RCDID => 2017
OTH => " Mustered out of Company I 24th Regiment Infantry"
SORT => "111847"
DRM => "ff"
SVCDAT => "10 Jun 1865"
pATTR (item) => MilSvc: Civil War, US Army, , Mustered out of Company I 24th Regiment Infantry
DATES => "(1847 - 1930)"
SEX => "M"

And the sort is now, based on earlier convos, remembered:

table.sort(GEDRCD, function(a, b) return a.NAME < b.NAME end)
table.sort(GEDRCD, sortsvc)


local function sortsvc(a, b)
if a.NAME == b.NAME then
return a.DSFSVC < b.DSFSVC
end
return a.NAME < b.NAME
end

Re: sort within a sort

Posted: 02 Sep 2019 15:51
by tatewise
Please read the FH Help page for Date Formats. Not arcane at all.
If the XDATETYPE is 'Before' what does it say XDATE1 contains?

Your script is FAR too complex and repetitive.
Try these few lines instead of your forty lines.
They should be faster as they use local date point methods:
local date = fhGetValueAsDate(dptr)
local xtyp = date:GetSubtype()
local xdat = date:GetDatePt1()
if xtyp == 'Before' or xtyp == 'To' then xdat = date:GetDatePt2() end
if xtyp == 'Between' or xtyp == 'From-To' then xtyp = 'From' end
-- not sure how you use xtyp & ytyp
local year = xdat:GetYear()
local month = xdat:GetMonth()
local day = xdat:GetDay()
if year == 0 then return '' end
if month == 0 then month = 7 end
if day == 0 then day = 1 end
local dsf = string.format("%04d%02d%02d",year,month,day)
return dsf


Your sorting should work OK, but does not need table.sort(GEDRCD, function(a, b) return a.NAME < b.NAME end) as the table.sort(GEDRCD, sortsvc) does it all.

Re: sort within a sort

Posted: 02 Sep 2019 19:23
by Ron Melby
Gnarley-- here it is now:

Code: Select all

function crtDSF(dptr)  
  local xdat = ''
  local date = ''
  local year = ''
  local month = ''
  local day = ''

  local dsf = ''

  dptr   = fhGetItemPtr(dptr, '~.DATE')
  if dptr:IsNull() then
    return ''
  end

  date = fhGetValueAsDate(dptr)
  xtyp = date:GetSubtype()
  xdat = date:GetDatePt1()

  year = xdat:GetYear()
  month = xdat:GetMonth()
  day = xdat:GetDay()

  if xtyp == 'Approximate' then
    month = 07
    day = 0
  end
  if xtyp == 'After' then
    month = 12
    day = 31
  end
  if xtyp == 'Before' then
    month = 0
    day = 0
  end
 if xtyp == 'From-To'
  or xtyp == 'From' then
    month = 1
    day = 1
  end
-- Between
-- Calculated
-- Estimated

  dsf = string.format("%04d%02d%02d", year, month, day)
  return dsf
end
*NB: this is a logical sorting field and per se is not a date. works grandly. Thanks (lost about 200 or more lines of code altogether)

Re: sort within a sort

Posted: 22 Sep 2019 17:59
by Ron Melby
earlier it was said this is extensible:


function AREASORT(a, b)
if a.AREA == b.AREA then
return a.GADR < b.GADR
end
return a.AREA < b.AREA
end


I need to extend this:

AREA (county level of)
GADR (grave address)
then need sorted by
NAME

So, all the graves in Kent (ok sort is fine)
sorted by cemetery (ok sort is fine)
and by name in cemetery (dont know how to extend fn AREASORT to do this.

Re: sort within a sort

Posted: 23 Sep 2019 20:53
by tatewise
Can't you see the pattern?

Sort by AREA needs:
return a.AREA < b.AREA

Sort by AREA and then by GADR needs:
if a.AREA == b.AREA then
return a.GADR < b.GADR
end
return a.AREA < b.AREA


Notice how return a.GADR < b.GADR is just like return a.AREA < b.AREA

So what do you think sort by AREA and then by GADR and then by NAME needs?

Just replace return a.GADR < b.GADR with the structure for GADR and NAME similar to the way return a.AREA < b.AREA is replaced by the structure for AREA and GADR. That pattern can repeat indefinitely.
e.g.
The pattern to sort by X and then Y is
if a.X == b.X then
return a.Y < b.Y
end
return a.X < b.X

where X = AREA and Y = GADR or X = GADR and Y = NAME

Re: sort within a sort

Posted: 29 Sep 2019 20:58
by Ron Melby
function ACNSORT(a, b)
if a.AREA == b.AREA then
return a.GADR < b.GADR
end
if a.GADR == b.GADR then
return a.NAME < b.NAME
end
return a.AREA < b.AREA
end

obviously, your example didnt do it.

I intend to
group by area, then cemetery within that area alphabetical, then name alphabetical within the cemetery.

that sort posted isnt it.

Re: sort within a sort

Posted: 30 Sep 2019 09:31
by tatewise
You are not following the pattern so try:

Code: Select all

function ACNSORT(a, b)
  if a.AREA == b.AREA then
    if a.GADR == b.GADR then
      return a.NAME < b.NAME
    end
    return a.GADR < b.GADR
  end
  return a.AREA < b.AREA
end
Can you see the logic?
If AREA the same and GADR the same then sort by NAME.
If AREA the same but GADR differ then sort by GADR.
If AREA differ then sort by AREA.