I have two parameters in a template, 'location' and 'locality_subjects'. Each can contain multiple values separated by a semicolon.
For instance:
|location=Bucks County, Pennsylvania;Chester County, Pennsylvania
|locality_subjects=Court records;Probate records;Vital records
I would like to create categories for each of these combinations:
[[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]]
I can do it pretty clumsily by using something like this, assuming that the maximum number of values each parameter could potentially contain is 4:
[[Category:{{#explode:{{{location|}}}|;|0}}, {{#explode:{{lc:{{{locality_subjects|}}}|;|0}}]]
[[Category:{{#explode:{{{location|}}}|;|0}}, {{#explode:{{lc:{{{locality_subjects|}}}|;|1}}]]
[[Category:{{#explode:{{{location|}}}|;|0}}, {{#explode:{{lc:{{{locality_subjects|}}}|;|2}}]]
[[Category:{{#explode:{{{location|}}}|;|0}}, {{#explode:{{lc:{{{locality_subjects|}}}|;|3}}]]
[[Category:{{#explode:{{{location|}}}|;|1}}, {{#explode:{{lc:{{{locality_subjects|}}}|;|0}}]]
[[Category:{{#explode:{{{location|}}}|;|1}}, {{#explode:{{lc:{{{locality_subjects|}}}|;|1}}]]
[[Category:{{#explode:{{{location|}}}|;|1}}, {{#explode:{{lc:{{{locality_subjects|}}}|;|2}}]]
[[Category:{{#explode:{{{location|}}}|;|1}}, {{#explode:{{lc:{{{locality_subjects|}}}|;|3}}]]
[[Category:{{#explode:{{{location|}}}|;|2}}, {{#explode:{{lc:{{{locality_subjects|}}}|;|0}}]]
[[Category:{{#explode:{{{location|}}}|;|2}}, {{#explode:{{lc:{{{locality_subjects|}}}|;|1}}]]
[[Category:{{#explode:{{{location|}}}|;|2}}, {{#explode:{{lc:{{{locality_subjects|}}}|;|2}}]]
[[Category:{{#explode:{{{location|}}}|;|2}}, {{#explode:{{lc:{{{locality_subjects|}}}|;|3}}]]
[[Category:{{#explode:{{{location|}}}|;|3}}, {{#explode:{{lc:{{{locality_subjects|}}}|;|0}}]]
[[Category:{{#explode:{{{location|}}}|;|3}}, {{#explode:{{lc:{{{locality_subjects|}}}|;|1}}]]
[[Category:{{#explode:{{{location|}}}|;|3}}, {{#explode:{{lc:{{{locality_subjects|}}}|;|2}}]]
[[Category:{{#explode:{{{location|}}}|;|3}}, {{#explode:{{lc:{{{locality_subjects|}}}|;|3}}]]
It seems like there must be a better way?
If you are willing to use Scribunto, you could create a module with a function that would produce a Cartesian product of all lists passed and format all items of it:
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 _, list in ipairs (frame.args) do
sets[#sets + 1] = split (trim (list), splitter)
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
}
(see example, except there are colons before Category
).
To use it in in your template, add
{{#invoke:Test/combine|combine
| {{{location}}}
| {{{locality_subjects}}}
| format = [[Category:%s, %s]]
}}