* KB: Ancestor and Descendant List Creation

Post here to suggest corrections, additions, changes etc to the FHUG KnowledgeBase . Include as much information as possible to help editors act on your post.

Moderator: kb admin

Post Reply
User avatar
Ron Melby
Megastar
Posts: 928
Joined: 15 Nov 2016 15:40
Family Historian: V6.2

KB: Ancestor and Descendant List Creation

Post by Ron Melby »

https://www.fhug.org.uk/kb/code-snippet ... -creation/

looping style GetAncestorList does not work.
The entire codesnip is nonsensical.
first: it does not compile.
there is a bottom half of a non existant loop at line 45 and 46.
moving the iLoop counter to line 44 and removing the end at 47; it will compile.
it is missing a moveto at line 37.

the movenext at line 44 relies on a pointer that is never set.
and the movenext statement is nonsensical in what the code is reporting to accomplish.
it needs an initializer to convert the incoming individual pointer to a family as child pointer
at each table insert, the famc pointer needs to be retrieved.
it does not cater to same sex as all the other functions do.

However, correcting all those mistakes it simply becomes a recursive function.
I am not clever enough to figure out how to accomplish it in a loop.
FH V.6.2.7 Win 10 64 bit
User avatar
tatewise
Megastar
Posts: 28519
Joined: 25 May 2010 11:00
Family Historian: V7
Location: Torbay, Devon, UK
Contact:

Re: KB: Ancestor and Descendant List Creation

Post by tatewise »

It is not my code but you are correct there are multiple mistakes in the script.
I think the following is the correct code with looping corrections in GetAncestorList.
It also caters for same-sex parents. The spelling of 'descendant' is corrected throughout.
For descendants, the recursive version includes descendants of spouses of descendants too.

Code: Select all

--[[
@function: CheckDuplicate
@description: Adds Record Id as value and index, to table if it does not already exist
@parameters: Item Pointer - Must be at Record Level
@returns: true if pointer is a duplicate
@requires: none
]] 
function CheckDuplicate(table, ptr)
  local id = fhGetRecordId(ptr)
  if table[id] == nil then
      table[id] = id
      return false
      else
      return true
  end
end
-- End Function
--[[
@function: GetAncestorList
@description: Returns a list of Ancestors
@parameters: Item Pointer - Must be at Record Level
@returns: table of record Item Pointers
@requires: CheckDuplicate
]] 
function GetAncestorList(ptr)
    local ancestorlist  = {}
    local dupcheck = {}

    local ptrMother = fhNewItemPtr()
    local ptrFather = fhNewItemPtr()
    local ptrFamily = fhNewItemPtr()

    table.insert(ancestorlist,ptr:Clone())
    CheckDuplicate(dupcheck,ptr)
    iLoop = 1
    while iLoop <= #ancestorlist do
        local ptrBase = ancestorlist[iLoop]
        ptrFamily:MoveTo(ptrBase,'~.FAMC')
        while ptrFamily:IsNotNull() do
            ptrMother:MoveTo(fhGetValueAsLink(ptrFamily),'~.WIFE[1]>')
            if ptrMother:IsNotNull() and (not CheckDuplicate(dupcheck,ptrMother))then
                table.insert(ancestorlist,ptrMother:Clone())
            end
            ptrMother:MoveTo(fhGetValueAsLink(ptrFamily),'~.WIFE[2]>')
            if ptrMother:IsNotNull() and (not CheckDuplicate(dupcheck,ptrMother))then
                table.insert(ancestorlist,ptrMother:Clone())
            end
            ptrFather:MoveTo(fhGetValueAsLink(ptrFamily),'~.HUSB[1]>')
            if ptrFather:IsNotNull() and (not CheckDuplicate(dupcheck,ptrFather)) then
                table.insert(ancestorlist,ptrFather:Clone())
            end
            ptrFather:MoveTo(fhGetValueAsLink(ptrFamily),'~.HUSB[2]>')
            if ptrFather:IsNotNull() and (not CheckDuplicate(dupcheck,ptrFather)) then
                table.insert(ancestorlist,ptrFather:Clone())
            end
            ptrFamily:MoveNext('SAME_TAG')
        end
        iLoop = iLoop + 1
    end
    return ancestorlist
end
-- End Function
--[[
@function: GetDescendantList
@description: Returns a list of descendants
@parameters: Item Pointer - Must be at Record Level
@returns: table of record Item Pointers
@requires: CheckDuplicate
]] 
function GetDescendantList(ptr)
    local descendantlist  = {}
    local dupcheck = {}
    local ptrChild = fhNewItemPtr()

    local ptrFamily = fhNewItemPtr()
    local ptrFamilyRec = fhNewItemPtr()
    local ptrBase   = fhNewItemPtr

    table.insert(descendantlist,ptr:Clone())
    CheckDuplicate(dupcheck,ptr)
    iLoop = 1
    while iLoop <= #descendantlist do
        ptrBase = descendantlist[iLoop]
        -- Loop Family as Spouse
        ptrFamily:MoveTo(ptrBase,'~.FAMS')
        while ptrFamily:IsNotNull() do
            ptrFamilyRec = fhGetValueAsLink(ptrFamily)
            -- Loop Children
            ptrChild:MoveTo(ptrFamilyRec,'~.CHIL')
            while ptrChild:IsNotNull() do 
              local ptrChildRecord = fhGetValueAsLink(ptrChild)
                if ptrChildRecord:IsNotNull() and not CheckDuplicate(dupcheck,ptrChildRecord) then
                    table.insert(descendantlist,fhGetValueAsLink(ptrChild))
                end
                ptrChild:MoveNext('SAME_TAG')
            end
            ptrFamily:MoveNext('SAME_TAG')
        end
        iLoop = iLoop + 1
    end
    return descendantlist
end
-- End Function

local ptrRoot = fhCallBuiltInFunction("FileRoot")
local tblAncs = GetAncestorList(ptrRoot)
local tblDesc = GetDescendantList(ptrRoot)
Mike Tate ~ researching the Tate and Scott family history ~ tatewise ancestry
User avatar
ColeValleyGirl
Megastar
Posts: 5528
Joined: 28 Dec 2005 22:02
Family Historian: V7
Location: Cirencester, Gloucestershire
Contact:

Re: KB: Ancestor and Descendant List Creation

Post by ColeValleyGirl »

Can I assume you'll correct the KB, Mike?
User avatar
Ron Melby
Megastar
Posts: 928
Joined: 15 Nov 2016 15:40
Family Historian: V6.2

Re: KB: Ancestor and Descendant List Creation

Post by Ron Melby »

there is also an unused pointer in loop descendant:
ptrFamilyRec = fhNewItemPtr()
probably should be:
ptrFamilyRecord = fhNewItemPtr()

and for consistency should add:
local ptrChildRecord = fhNewItemPtr()
FH V.6.2.7 Win 10 64 bit
User avatar
tatewise
Megastar
Posts: 28519
Joined: 25 May 2010 11:00
Family Historian: V7
Location: Torbay, Devon, UK
Contact:

Re: KB: Ancestor and Descendant List Creation

Post by tatewise »

I included changes for both those issues in the script I posted earlier.

Does the new script work OK for you Ron?

If so, then I will update the KB.
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: KB: Ancestor and Descendant List Creation

Post by Ron Melby »

I have now run the two looping scripts, they are fine.

havent done the recursives yet.
FH V.6.2.7 Win 10 64 bit
Post Reply