Module:Cartesian with comma
From Ross Surname Project
More actions
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
}