* sort within a sort

For users to report plugin bugs and request plugin enhancements; and for authors to test new/new versions of plugins, and to discuss plugin development (in the Programming Technicalities sub-forum). If you want advice on choosing or using a plugin, please ask in General Usage or an appropriate sub-forum.
Post Reply
User avatar
Ron Melby
Megastar
Posts: 928
Joined: 15 Nov 2016 15:40
Family Historian: V6.2

sort within a sort

Post 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?
FH V.6.2.7 Win 10 64 bit
User avatar
tatewise
Megastar
Posts: 28410
Joined: 25 May 2010 11:00
Family Historian: V7
Location: Torbay, Devon, UK
Contact:

Re: sort within a sort

Post 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.
Mike Tate ~ researching the Tate and Scott family history ~ tatewise ancestry
User avatar
Ron Melby
Megastar
Posts: 928
Joined: 15 Nov 2016 15:40
Family Historian: V6.2

Re: sort within a sort

Post 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
FH V.6.2.7 Win 10 64 bit
User avatar
tatewise
Megastar
Posts: 28410
Joined: 25 May 2010 11:00
Family Historian: V7
Location: Torbay, Devon, UK
Contact:

Re: sort within a sort

Post 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.
Mike Tate ~ researching the Tate and Scott family history ~ tatewise ancestry
User avatar
Ron Melby
Megastar
Posts: 928
Joined: 15 Nov 2016 15:40
Family Historian: V6.2

Re: sort within a sort

Post 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)
FH V.6.2.7 Win 10 64 bit
User avatar
Ron Melby
Megastar
Posts: 928
Joined: 15 Nov 2016 15:40
Family Historian: V6.2

Re: sort within a sort

Post 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.
FH V.6.2.7 Win 10 64 bit
User avatar
tatewise
Megastar
Posts: 28410
Joined: 25 May 2010 11:00
Family Historian: V7
Location: Torbay, Devon, UK
Contact:

Re: sort within a sort

Post 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
Mike Tate ~ researching the Tate and Scott family history ~ tatewise ancestry
User avatar
Ron Melby
Megastar
Posts: 928
Joined: 15 Nov 2016 15:40
Family Historian: V6.2

Re: sort within a sort

Post 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.
FH V.6.2.7 Win 10 64 bit
User avatar
tatewise
Megastar
Posts: 28410
Joined: 25 May 2010 11:00
Family Historian: V7
Location: Torbay, Devon, UK
Contact:

Re: sort within a sort

Post 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.
Mike Tate ~ researching the Tate and Scott family history ~ tatewise ancestry
Post Reply