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.