Module:Array: Difference between revisions

From Honkai: Nexus Anima Wiki
Jump to navigation Jump to search
Created page with "local p = {} local lib = require('Module:Feature') function p.main(frame) local args = require('Module:Arguments').getArgs(frame, { wrapper = { 'Template:Array' } }) --mw.logObject(args,'args') --debug return p._main(args, frame) end function p._main(args, frame) local arrayString = args[1] or nil local separator = args[2] or args.delim or nil local form = args[3] or args['format'] or nil local join = args[4] or args.join or '' local dedupe = args['dedupe']..."
 
Kwwxis (talk | contribs)
Add more features from Array module in zzz/wuwa wikis
Line 4: Line 4:
function p.main(frame)
function p.main(frame)
local args = require('Module:Arguments').getArgs(frame, {
local args = require('Module:Arguments').getArgs(frame, {
parentFirst = true,
wrapper = { 'Template:Array' }
wrapper = { 'Template:Array' }
})
})
--mw.logObject(args,'args') --debug
return p._main(args, frame)
return p._main(args, frame)
end
end


function p._main(args, frame)
function p._main(args, frame)
local arrayString = args[1] or nil
local arrayString = args[1] or args["arrayString"] or nil
local separator = args[2] or args.delim or nil
local separator = args[2] or args["sep"] or args["delim"] or args["separator"] or nil
local form = args[3] or args['format'] or nil
local format = args[3] or args["format"] or "{item}"
local join = args[4] or args.join or ''
local join = args[4] or args["join"] or ""
local dedupe = args['dedupe'] or nil
local dedupe = args["dedupe"] or nil
local sort = args['sort'] or nil
local sort = args["sort"] or nil
local sentence = args['sentence'] or nil
local sentence = args["sentence"] or nil
local template = args['template'] or nil
local sentence_last = args['sentence_last'] or ' and '
local sentence_join = args['sentence_join'] or ', '
local firstItemOnly = args["firstItemOnly"] or nil
local offsetStart = args["offsetStart"] or nil
local offsetEnd = args["offsetEnd"] or nil
local prefix = args['prefix'] or ''
local prefix = args['prefix'] or ''
local suffix = args['suffix'] or ''
local suffix = args['suffix'] or ''
local sentence_last = args['sentence_last'] or ' and '
local template = args['template'] or nil
local sentence_join = args['sentence_join'] or ', '
local sub_separator = args.subsep or nil
local split_opt = {
local split_opt = {
removeEmpty = args['removeEmpty'] or nil,
removeEmpty = args['removeEmpty'] or nil,
Line 30: Line 32:


-- argument validation
-- argument validation
if arrayString == nil then return '' end
if arrayString == nil then return "" end
if separator == nil then return error('Second argument (separator) must not be empty.') end
if separator == nil then return error("Second argument (separator) must not be empty.") end
if separator == '' then return error('Second argument (separator) must not be empty string.') end
if separator == "" then return error("Second argument (separator) must not be empty string.") end
if form == nil then return error('Third argument (format) must not be empty.') end
if format == nil then return error("Third argument (format) must not be empty.") end
if form:find('{item[%d%.]*}') == nil then return error('Third argument (format) does not include {item}.') end


-- split string to array
-- split string to array
if string.find(separator, "{newline}") then
separator = separator:gsub("{newline}", "\n")
end
if string.find(separator, "{space}") then
separator = separator:gsub("{space}", " ")
end
local array = lib.split(arrayString, separator, split_opt)
local array = lib.split(arrayString, separator, split_opt)


-- remove duplcates from array
-- remove duplicates from array
if dedupe == '1' then
if dedupe ~= nil then
array = p._removeDuplicates(array)
array = p._removeDuplicates(array)
end
end
Line 47: Line 54:
if sort ~= nil then
if sort ~= nil then
array = p._sort(array, sort)
array = p._sort(array, sort)
end
-- filter by offset
if offsetStart ~= nil or offsetEnd ~= nil then
array = lib.arraySlice(array, lib.toNullableNumber(offsetStart), lib.toNullableNumber(offsetEnd))
end
end
-- replace keywords in array
-- replace keywords in array
for key, value in pairs(array) do
for key, value in pairs(array) do
local item = form
-- get format (may have override)
item = item:gsub('{newline}', '\n')
local item = format
item = item:gsub('{index}', key)
if args["format" .. key] ~= nil then
item = args["format" .. key]
end
-- Basic substitutions
if string.find(item, "{index}") then
item = item:gsub("{index}", key)
end
if string.find(item, "{newline}") then
item = item:gsub("{newline}", "\n")
end
if string.find(item, "{space}") then
item = item:gsub("{space}", " ")
end
-- figure out sub-divisions if any
-- figure out sub-divisions if any
Line 70: Line 95:
split(values, '2')
split(values, '2')
item = item:gsub('{item}', value)
-- Item substitutions
item = item:gsub("{item}", value)
item = item:gsub('{item([%d%.]*)}',
item = item:gsub('{item([%d%.]*)}',
function(suffix)
function(suffix)
Line 85: Line 111:
end
end
)
)
if string.find(item, "{itemLink}") then
item = item:gsub("{itemLink}", mw.InfoboxBuilderHF.Link(value))
end
if string.find(item, "{itemLinkSafe}") then
item = item:gsub("{itemLinkSafe}", mw.InfoboxBuilderHF.Link_safe(value))
end
array[key] = item
array[key] = item
end
end
Line 92: Line 123:
-- create result array
-- create result array
local result = ''
local result = ""
-- join as sentence
-- join as sentence
if sentence ~= nil then
if sentence ~= nil then
if #array == 0 then return ''
if #array == 0 then return ""
elseif #array == 1 then result =  array[1]
elseif #array == 1 then return array[1]
elseif #array == 2 then result =  array[1] .. sentence_last .. array[2]
elseif #array == 2 then return array[1] .. sentence_last .. array[2]
else
else
local last = table.remove(array, #array)
local last = table.remove(array, #array)
result = table.concat(array, sentence_join) .. ',' .. sentence_last .. last
result = table.concat(array, sentence_join) .. sentence_join .. sentence_last .. last
end
end
-- first item only
elseif firstItemOnly ~= nil then
return array[1]
-- join with join string
-- join with join string
else
else
result = table.concat(array, join):gsub('{newline}', '\n'):gsub('{space}', ' ')--in case joining string contains keyword
if string.find(join, "{newline}") then
join = join:gsub("{newline}", "\n")
end
if string.find(join, "{space}") then
join = join:gsub("{space}", " ")
end
result = table.concat(array, join)
end
end
result = prefix .. result .. suffix
result = prefix .. result .. suffix
if template then
if template then
if args.debug then mw.logObject(result, 'final result pre-preprocess') end
if args.debug then mw.logObject(result, 'final result pre-preprocess') end
Line 144: Line 185:
function p._sort(arr, dir)
function p._sort(arr, dir)
local order = nil
local order = nil
if (dir == -1 or dir == '-1') then
if (dir == -1 or dir == "-1") then
order = function(tVal, a, b) return a > b end
order = function(tVal, a, b) return a > b end
elseif (dir == 1 or dir == '1') then
elseif (dir == 1 or dir == "1") then
order = function(tVal, a, b) return a < b end
order = function(tVal, a, b) return a < b end
else
else

Revision as of 11:51, 29 August 2025

Documentation for this module may be created at Module:Array/doc

local p = {}
local lib = require('Module:Feature')

function p.main(frame)
	local args = require('Module:Arguments').getArgs(frame, {
		parentFirst = true,
		wrapper = { 'Template:Array' }
	})
	return p._main(args, frame)
end

function p._main(args, frame)
	local arrayString = args[1] or args["arrayString"] or nil
	local separator = args[2] or args["sep"] or args["delim"] or args["separator"] or nil
	local format = args[3] or args["format"] or "{item}"
	local join = args[4] or args["join"] or ""
	local dedupe = args["dedupe"] or nil
	local sort = args["sort"] or nil
	local sentence = args["sentence"] or nil
	local sentence_last = args['sentence_last'] or ' and '
	local sentence_join = args['sentence_join'] or ', '
	local firstItemOnly = args["firstItemOnly"] or nil
	local offsetStart = args["offsetStart"] or nil
	local offsetEnd = args["offsetEnd"] or nil
	local prefix = args['prefix'] or ''
	local suffix = args['suffix'] or ''
	local template = args['template'] or nil
	local split_opt = {
		removeEmpty = args['removeEmpty'] or nil,
		noTrim = args['noTrim'] or nil
	}

	-- argument validation
	if arrayString == nil then return "" end
	if separator == nil then return error("Second argument (separator) must not be empty.") end
	if separator == "" then return error("Second argument (separator) must not be empty string.") end
	if format == nil then return error("Third argument (format) must not be empty.") end

	-- split string to array
	if string.find(separator, "{newline}") then
		separator = separator:gsub("{newline}", "\n")
	end
	if string.find(separator, "{space}") then
		separator = separator:gsub("{space}", " ")
	end
	local array = lib.split(arrayString, separator, split_opt)

	-- remove duplicates from array
	if dedupe ~= nil then
		array = p._removeDuplicates(array)
	end
	
	-- sort array
	if sort ~= nil then
		array = p._sort(array, sort)
	end
	
	-- filter by offset
	if offsetStart ~= nil or offsetEnd ~= nil then
		array = lib.arraySlice(array, lib.toNullableNumber(offsetStart), lib.toNullableNumber(offsetEnd))
	end
	
	-- replace keywords in array
	for key, value in pairs(array) do
		-- get format (may have override)
		local item = format
		if args["format" .. key] ~= nil then
			item = args["format" .. key]
		end
		
		-- Basic substitutions
		if string.find(item, "{index}") then
			item = item:gsub("{index}", key)
		end
		if string.find(item, "{newline}") then
			item = item:gsub("{newline}", "\n")
		end
		if string.find(item, "{space}") then
			item = item:gsub("{space}", " ")
		end
		
		-- figure out sub-divisions if any
		function split(arr, index)
			if args['delim' .. index] then
				for v in lib.gsplit(arr.main, args['delim' .. index], split_opt) do
					local subarr = {main = v}
					split(subarr, tostring(tonumber(index)+1))
					table.insert(arr, subarr)
				end
			else
				return
			end
		end
		local values = { main = value }
		split(values, '2')
		
		-- Item substitutions
		item = item:gsub("{item}", value)
		item = item:gsub('{item([%d%.]*)}',
			function(suffix)
				local val = values
				for index in lib.gsplit(suffix, '.') do
					if val[tonumber(index)] then
						val = val[tonumber(index)]
					else
						val = {main=''}
						break
					end
				end
				return val.main
			end
		)
		if string.find(item, "{itemLink}") then
			item = item:gsub("{itemLink}", mw.InfoboxBuilderHF.Link(value))
		end
		if string.find(item, "{itemLinkSafe}") then
			item = item:gsub("{itemLinkSafe}", mw.InfoboxBuilderHF.Link_safe(value))
		end
		array[key] = item
	end
	
	if args.debug then mw.logObject(array, 'input array') end
	
	-- create result array
	local result = ""
	
	-- join as sentence
	if sentence ~= nil then
		if #array == 0 then return ""
		elseif #array == 1 then return array[1]
		elseif #array == 2 then return array[1] .. sentence_last .. array[2]
		else
			local last = table.remove(array, #array)
			result = table.concat(array, sentence_join) .. sentence_join .. sentence_last .. last
		end
	-- first item only
	elseif firstItemOnly ~= nil then
		return array[1]
	-- join with join string
	else
		if string.find(join, "{newline}") then
			join = join:gsub("{newline}", "\n")
		end
		if string.find(join, "{space}") then
			join = join:gsub("{space}", " ")
		end
		result = table.concat(array, join)
	end
	result = prefix .. result .. suffix
	
	if template then
		if args.debug then mw.logObject(result, 'final result pre-preprocess') end
		if not args.nodpl then
			result = result
				:gsub('²{','{{')
				:gsub('}²','}}')
				:gsub('¦','|')
		end
		result = result
			:gsub('%^2{','{{')	-- for use inside DPL
			:gsub('}%^2','}}')	--
			:gsub('¹','|')		--
		result = frame:preprocess(result)
	end
	
	if args.debug then mw.logObject(result, 'final result') end
	
	return result
end

function p._removeDuplicates(arr)
	local hash = {}
	local res = {}

	for _,v in ipairs(arr) do
	   if (not hash[v]) then
	       res[#res+1] = v
	       hash[v] = true
	   end
	end

	return res
end

function p._sort(arr, dir)
	local order = nil
	if (dir == -1 or dir == "-1") then
		order = function(tVal, a, b) return a > b end
	elseif (dir == 1 or dir == "1") then
		order = function(tVal, a, b) return a < b end
	else
		return arr
	end
	table.sort(arr, function(a, b) return order(t, a, b) end)
	return arr
end

return p