Translating code sets

This article was originally written for Iguana 5 so it contains version 5 screenshots, and may contain out of date references.

There are two versions of the codemap module: one allows for a default value to be returned if there is no matching code, the second returns nil if there is no match. To change the behaviour just substitute the preferred module.

The source code for both versions is at the bottom of the page.

Simple list.

You can define a list like this:

Code translation table.

Looking up unknown code “W” returns nil:

Now we add a default so “other” is returned:

If we use the second module without support for default values, then the “other”, default value, is ignored:

Translate mixed alphanumeric codes.

You can use any value as the key (code) in your codemap table:

Translate codes from a database.

Or translating codes taken from external database table:

The code was written to allow for a default value:

If you do not need the default behaviour, you can use the second version of the module.

We also added a condition to handle an unidentified code:

You can see these examples in action by pasting this code into a Translator instance:

local codemap = require 'codemap'

-- Best Practice: use local functions
-- main() is last so it can use the local functions

MySet = codemap.set{"Fred", "Bruce", "Jim"}

local function Map()
   local A = 'Fred'
   if MySet[A] then
      trace('Hello friend')
   end   

end

SexCodeMap = codemap.map({
      M='Male',
      m='Male',
      F='Female',
      f='Female' 
   },'other')

local function MapSex()
   local V = 'M'
   local W = ''
   local A = SexCodeMap[V]
   local B = SexCodeMap[W]
   trace(A)
   trace(B)
end

RelationCodeMap = codemap.map{
   ['01']='Spouse',
   ['4f']='Grandparent',
   ['G7']='Nephew or Niece'
}

local function MapRelationship()
   local V = '4f'
   local A = RelationCodeMap[V]
   trace(A)
end

------------------------------
-- database example functions
------------------------------

-- create database, tables and data
local function CreateProcedures()
   -- create database
   local Conn = db.connect{
      api=db.SQLITE,
      name='map.sqlite',
      live = true}

   -- create table
   Conn:execute{sql=[[
      CREATE TABLE IF NOT EXISTS Procedure (
      Procedure Text(255) NOT NULL PRIMARY KEY,
      Code Text(255) )
      ]],  
      live = true}

   -- insert/replace data
   Conn:execute{sql="REPLACE INTO Procedure VALUES('procA','codeA')",  
      live = true}
   Conn:execute{sql="REPLACE INTO Procedure VALUES('procB','codeB')",  
      live = true}
   Conn:execute{sql="REPLACE INTO Procedure VALUES('procC','codeC')",  
      live = true}
end

local function ReadRset()
   local Conn = db.connect{
      api=db.SQLITE,
      name='map.sqlite',
      live = true}
   return Conn:query('SELECT * FROM Procedure')
end

local function RequestCodeMap(R)
   local t = {}
   for i = 1,#R do 
      t[R[i].Procedure:nodeValue()] = R[i].Code:nodeValue()
   end
   return codemap.map(t,'other')
end

local function MapProcedures()
   local R = ReadRset()
   local ProceduresCodeMap = RequestCodeMap(R)

   local V = R[1].Procedure:nodeValue()
   local A = ProceduresCodeMap[V]
   trace(A)

   V = 'procB'
   A = ProceduresCodeMap[V]
   trace(A)

   V = 'procD' -- any value not in the procedure table
   A = ProceduresCodeMap[V]
   trace (A)
end

function main()
   Map()
   MapSex()
   MapRelationship()

   CreateProcedures() -- create DB, table & data
   MapProcedures() 
end

The code to the codemap module is below. It does make use of an advanced Lua feature called metatables. However, it’s not necessary to understand metatables to use the module.

Version with default return:

-- This code map library has a number of useful helper routines for doing mapping and checking codes etc.

local codemap = {}

-- Make a set
-- MySet = codemap.set{"Fred", "Bruce", "Jim"}
-- if MySet[Msg.PID[3][1][1]] then print('One of our three amigos') end
function codemap.set(a)
   local m = {}
   for _,v in ipairs(a) do m[v] = true end
   return codemap.map(m, false)
end

-- Create a map the advantage of this function is that it will take a tree node without
-- needing to convert it to a string.  Example of usage
-- SexMap = codemap.map({'M'='Male', 'm'='Male', 'F'='Female', 'f'='Female'},'defaultValue')
function codemap.map(m, default)
   return setmetatable(m, {
         __index = function(m,k)
            if type(k) ~= 'string' then
               local v = rawget(m, tostring(k))
               if v ~= nil then return v end
            end
            return default
         end})
end

return codemap

Version without default:

-- This code map library has a number of useful helper routines for doing mapping and checking codes etc.

local codemap = {}

-- Make a set
-- MySet = codemap.set{"Fred", "Bruce", "Jim"}
-- if MySet[Msg.PID[3][1][1]] then print('One of our three amigos') end
function codemap.set(List)
   local set = {}
   for _, V in ipairs(List) do set[V] = true end

   setmetatable(set, set_met)
   return set
end

-- Create a map the advantage of this function is that it will take a tree node without
-- needing to convert it to a string.  Example of usage
-- SexMap = codemap.map{'M'='Male', 'm'='Male', 'F'='Female', 'f'='Female'}
function codemap.map(Map)
   setmetatable(Map, set_met)
   return Map
end

set_met = {}
function set_met.__index(T, Key)
   if type(Key) ~= 'string' then
      return T[tostring(Key)] 
   end
   return nil
end

return codemap

 

Leave A Comment?