Toggle menu
Toggle preferences menu
Toggle personal menu
Not logged in
Your IP address will be publicly visible if you make any edits.

Module:Cartesian with comma

From Ross Surname Project

This module computes and returns the cartesian product of multiple input sets (i.e., lists of strings), and then formats and combines the results into a single output string. Because this module was original developed to deal with locations, if a value in the first set contains a comma, a comma will be added to the end of that value before it is combined with a value from the second set.

Example

It is called by {{Combine categories}} to create category names from a list of locations and a list of topics.

{{#invoke:Cartesian categories|combine
    | {{{location}}}
    | {{lc:{{{locality_subjects}}}}}
    | format = [[Category:%s %s]]
}}

Input:

{{Combine categories
|location=Bucks County, Pennsylvania;Chester County, Pennsylvania;Pennsylvania
|locality_subjects=Court records;Probate records;Vital records
}}

Output:

[[Category:Pennsylvania court records]]
[[Category:Pennsylvania probate records]]
[[Category:Pennsylvania vital records]]
[[Category:Bucks County, Pennsylvania, court records]]
[[Category:Bucks County, Pennsylvania, probate records]]
[[Category:Bucks County, Pennsylvania, vital records]]
[[Category:Chester County, Pennsylvania, court records]]
[[Category:Chester County, Pennsylvania, probate records]]
[[Category:Chester County, Pennsylvania, vital records]]

See also

Acknowledgements

Original code provided by Alexander Mashin.


local remove, insert, concat = table.remove, table.insert, table.concat
local split, trim = mw.text.split, mw.text.trim
local clone = mw.clone

local function cartesian (sets)
    local product = {}
    local set = remove (sets)
    if #sets == 0 then
        for _, item in ipairs (set) do
            insert (product, { item })
        end
        return product
    end
    for __, first in ipairs (cartesian (sets)) do
        for _, second in ipairs (set) do
            insert (product, clone (first))
            insert (product [#product], second)
        end
    end
    return product
end

local function format_array (array, format, separator)
    local formatted = {}
    for _, combination in ipairs (array) do
        insert (formatted, format:format (unpack (combination)))
    end
    return concat (formatted, separator)
end
        
return {
combine = function (frame)
    local sets = {}
    local delimiter = frame.args.delimiter or ';'
    local splitter = '%s*' .. delimiter .. '%s*'
    local default_format = {}
    for i, list in ipairs (frame.args) do
        local items = split (trim (list), splitter)
        -- If this is the first set, add a comma to items that contain a comma
        if i == 1 then
            for j, item in ipairs(items) do
                if item:find(',') then
                    items[j] = item .. ','
                end
            end
        end
        sets[#sets + 1] = items
        insert (default_format, '%s')
    end
    local format = frame.args.format or concat (default_format, ', ')
    local separator = frame.args.separator or '\n'
    return format_array (cartesian (sets), format, separator)
end
}