<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://mywikibiz.com/index.php?action=history&amp;feed=atom&amp;title=Module%3ASet</id>
	<title>Module:Set - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://mywikibiz.com/index.php?action=history&amp;feed=atom&amp;title=Module%3ASet"/>
	<link rel="alternate" type="text/html" href="https://mywikibiz.com/index.php?title=Module:Set&amp;action=history"/>
	<updated>2026-06-20T17:21:35Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.35.3</generator>
	<entry>
		<id>https://mywikibiz.com/index.php?title=Module:Set&amp;diff=479416&amp;oldid=prev</id>
		<title>Zoran: Pywikibot 6.4.0</title>
		<link rel="alternate" type="text/html" href="https://mywikibiz.com/index.php?title=Module:Set&amp;diff=479416&amp;oldid=prev"/>
		<updated>2021-07-16T05:56:34Z</updated>

		<summary type="html">&lt;p&gt;Pywikibot 6.4.0&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;--[[&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
--                                   Set                                          --&lt;br /&gt;
--                                                                                --&lt;br /&gt;
-- This module includes a number of set operations for dealing with Lua tables.   --&lt;br /&gt;
-- It currently has union, intersection and complement functions for both         --&lt;br /&gt;
-- key/value pairs and for values only.                                           --&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
--]]&lt;br /&gt;
&lt;br /&gt;
-- Get necessary libraries and functions&lt;br /&gt;
local libraryUtil = require('libraryUtil')&lt;br /&gt;
local checkType = libraryUtil.checkType&lt;br /&gt;
local tableTools = require('Module:TableTools')&lt;br /&gt;
&lt;br /&gt;
local p = {}&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- Helper functions&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
--]]&lt;br /&gt;
&lt;br /&gt;
-- Makes a set from a table's values. Returns an array of all values with&lt;br /&gt;
-- duplicates removed.&lt;br /&gt;
local function makeValueSet(t)&lt;br /&gt;
	local isNan = tableTools.isNan&lt;br /&gt;
	local ret, exists = {}, {}&lt;br /&gt;
	for k, v in pairs(t) do&lt;br /&gt;
		if isNan(v) then&lt;br /&gt;
			-- NaNs are always unique, and they can't be table keys, so don't&lt;br /&gt;
			-- check for existence.&lt;br /&gt;
			ret[#ret + 1] = v&lt;br /&gt;
		elseif not exists[v] then&lt;br /&gt;
			exists[v] = true&lt;br /&gt;
			ret[#ret + 1] = v&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return ret&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- union&lt;br /&gt;
--&lt;br /&gt;
-- This returns the union of the key/value pairs of n tables. If any of the tables&lt;br /&gt;
-- contain different values for the same table key, the table value is converted&lt;br /&gt;
-- to an array holding all of the different values.&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
--]]&lt;br /&gt;
function p.union(...)&lt;br /&gt;
	local lim = select('#', ...) &lt;br /&gt;
	if lim &amp;lt; 2 then&lt;br /&gt;
		error(&amp;quot;too few arguments to 'union' (minimum is 2, received &amp;quot; .. lim .. ')', 2)&lt;br /&gt;
	end&lt;br /&gt;
	local ret, trackArrays = {}, {}&lt;br /&gt;
	for i = 1, lim do&lt;br /&gt;
		local t = select(i, ...)&lt;br /&gt;
		checkType('union', i, t, 'table')&lt;br /&gt;
		for k, v in pairs(t) do&lt;br /&gt;
			local retKey = ret[k]&lt;br /&gt;
			if retKey == nil then&lt;br /&gt;
				ret[k] = v&lt;br /&gt;
			elseif retKey ~= v then&lt;br /&gt;
				if trackArrays[k] then&lt;br /&gt;
					local array = ret[k]&lt;br /&gt;
					local valExists&lt;br /&gt;
					for _, arrayVal in ipairs(array) do&lt;br /&gt;
						if arrayVal == v then&lt;br /&gt;
							valExists = true&lt;br /&gt;
							break&lt;br /&gt;
						end&lt;br /&gt;
					end&lt;br /&gt;
					if not valExists then&lt;br /&gt;
						array[#array + 1] = v&lt;br /&gt;
						ret[k] = array&lt;br /&gt;
					end&lt;br /&gt;
				else&lt;br /&gt;
					ret[k] = {ret[k], v}&lt;br /&gt;
					trackArrays[k] = true&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return ret&lt;br /&gt;
end				&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- valueUnion&lt;br /&gt;
--&lt;br /&gt;
-- This returns the union of the values of n tables, as an array. For example, for&lt;br /&gt;
-- the tables {1, 3, 4, 5, foo = 7} and {2, bar = 3, 5, 6}, union will return&lt;br /&gt;
-- {1, 2, 3, 4, 5, 6, 7}.&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
--]]&lt;br /&gt;
function p.valueUnion(...)&lt;br /&gt;
	local lim = select('#', ...) &lt;br /&gt;
	if lim &amp;lt; 2 then&lt;br /&gt;
		error(&amp;quot;too few arguments to 'valueUnion' (minimum is 2, received &amp;quot; .. lim .. ')', 2)&lt;br /&gt;
	end&lt;br /&gt;
	local isNan = tableTools.isNan&lt;br /&gt;
	local ret, exists = {}, {}&lt;br /&gt;
	for i = 1, lim do&lt;br /&gt;
		local t = select(i, ...)&lt;br /&gt;
		checkType('valueUnion', i, t, 'table')&lt;br /&gt;
		for k, v in pairs(t) do&lt;br /&gt;
			if isNan(v) then&lt;br /&gt;
				ret[#ret + 1] = v&lt;br /&gt;
			elseif not exists[v] then&lt;br /&gt;
				ret[#ret + 1] = v&lt;br /&gt;
				exists[v] = true&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return ret&lt;br /&gt;
end	&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- intersection&lt;br /&gt;
--&lt;br /&gt;
-- This returns the intersection of the key/value pairs of n tables. Both the key&lt;br /&gt;
-- and the value must match to be included in the resulting table.&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
--]]&lt;br /&gt;
function p.intersection(...)&lt;br /&gt;
	local lim = select('#', ...) &lt;br /&gt;
	if lim &amp;lt; 2 then&lt;br /&gt;
		error(&amp;quot;too few arguments to 'intersection' (minimum is 2, received &amp;quot; .. lim .. ')', 2)&lt;br /&gt;
	end&lt;br /&gt;
	local ret, track, pairCounts = {}, {}, {}&lt;br /&gt;
	for i = 1, lim do&lt;br /&gt;
		local t = select(i, ...)&lt;br /&gt;
		checkType('intersection', i, t, 'table')&lt;br /&gt;
		for k, v in pairs(t) do&lt;br /&gt;
			local trackVal = track[k]&lt;br /&gt;
			if trackVal == nil then&lt;br /&gt;
				track[k] = v&lt;br /&gt;
				pairCounts[k] = 1&lt;br /&gt;
			elseif trackVal == v then&lt;br /&gt;
				pairCounts[k] = pairCounts[k] + 1&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	for k, v in pairs(track) do&lt;br /&gt;
		if pairCounts[k] == lim then&lt;br /&gt;
			ret[k] = v&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return ret&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- valueIntersection&lt;br /&gt;
--&lt;br /&gt;
-- This returns the intersection of the values of n tables, as an array. For&lt;br /&gt;
-- example, for the tables {1, 3, 4, 5, foo = 7} and {2, bar = 3, 5, 6}, &lt;br /&gt;
-- intersection will return {3, 5}.&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
--]]&lt;br /&gt;
&lt;br /&gt;
function p.valueIntersection(...)&lt;br /&gt;
	local lim = select('#', ...) &lt;br /&gt;
	if lim &amp;lt; 2 then&lt;br /&gt;
		error(&amp;quot;too few arguments to 'valueIntersection' (minimum is 2, received &amp;quot; .. lim .. ')', 2)&lt;br /&gt;
	end&lt;br /&gt;
	local isNan = tableTools.isNan&lt;br /&gt;
	local vals, ret = {}, {}&lt;br /&gt;
	local isSameTable = true -- Tracks table equality.&lt;br /&gt;
	local tableTemp -- Used to store the table from the previous loop so that we can check table equality.&lt;br /&gt;
	for i = 1, lim do&lt;br /&gt;
		local t = select(i, ...)&lt;br /&gt;
		checkType('valueIntersection', i, t, 'table')&lt;br /&gt;
		if tableTemp and t ~= tableTemp then&lt;br /&gt;
			isSameTable = false&lt;br /&gt;
		end&lt;br /&gt;
		tableTemp = t&lt;br /&gt;
		t = makeValueSet(t) -- Remove duplicates&lt;br /&gt;
		for k, v in pairs(t) do&lt;br /&gt;
			-- NaNs are never equal to any other value, so they can't be in the intersection.&lt;br /&gt;
			-- Which is lucky, as they also can't be table keys.&lt;br /&gt;
			if not isNan(v) then&lt;br /&gt;
				local valCount = vals[v] or 0&lt;br /&gt;
				vals[v] = valCount + 1&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	if isSameTable then&lt;br /&gt;
		-- If all the tables are equal, then the intersection is that table (including NaNs).&lt;br /&gt;
		-- All we need to do is convert it to an array and remove duplicate values.&lt;br /&gt;
		return makeValueSet(tableTemp)&lt;br /&gt;
	end&lt;br /&gt;
	for val, count in pairs(vals) do&lt;br /&gt;
		if count == lim then&lt;br /&gt;
			ret[#ret + 1] = val&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return ret&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- complement&lt;br /&gt;
--&lt;br /&gt;
-- This returns the relative complement of t1, t2, ..., in tn. The complement&lt;br /&gt;
-- is of key/value pairs. This is equivalent to all the key/value pairs that are in&lt;br /&gt;
-- tn but are not in t1, t2, ... tn-1.&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
--]]&lt;br /&gt;
function p.complement(...)&lt;br /&gt;
	local lim = select('#', ...) &lt;br /&gt;
	if lim &amp;lt; 2 then&lt;br /&gt;
		error(&amp;quot;too few arguments to 'complement' (minimum is 2, received &amp;quot; .. lim .. ')', 2)&lt;br /&gt;
	end&lt;br /&gt;
	--[[&lt;br /&gt;
	-- Now we know that we have at least two sets.&lt;br /&gt;
	-- First, get all the key/value pairs in tn. We can't simply make ret equal to tn,&lt;br /&gt;
	-- as that will affect the value of tn for the whole module.&lt;br /&gt;
	--]]&lt;br /&gt;
	local tn = select(lim, ...)&lt;br /&gt;
	checkType('complement', lim, tn, 'table')&lt;br /&gt;
	local ret = tableTools.shallowClone(tn)&lt;br /&gt;
	-- Remove all the key/value pairs in t1, t2, ..., tn-1.&lt;br /&gt;
	for i = 1, lim - 1 do&lt;br /&gt;
		local t = select(i, ...)&lt;br /&gt;
		checkType('complement', i, t, 'table')&lt;br /&gt;
		for k, v in pairs(t) do&lt;br /&gt;
			if ret[k] == v then&lt;br /&gt;
				ret[k] = nil&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return ret&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- valueComplement&lt;br /&gt;
--&lt;br /&gt;
-- This returns an array containing the relative complement of t1, t2, ..., in tn.&lt;br /&gt;
-- The complement is of values only. This is equivalent to all the values that are&lt;br /&gt;
-- in tn but are not in t1, t2, ... tn-1.&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
--]]&lt;br /&gt;
function p.valueComplement(...)&lt;br /&gt;
	local lim = select('#', ...) &lt;br /&gt;
	if lim &amp;lt; 2 then&lt;br /&gt;
		error(&amp;quot;too few arguments to 'valueComplement' (minimum is 2, received &amp;quot; .. lim .. ')', 2)&lt;br /&gt;
	end&lt;br /&gt;
	local isNan = tableTools.isNan&lt;br /&gt;
	local ret, exists = {}, {}&lt;br /&gt;
	for i = 1, lim - 1 do&lt;br /&gt;
		local t = select(i, ...)&lt;br /&gt;
		checkType('valueComplement', i, t, 'table')&lt;br /&gt;
		t = makeValueSet(t) -- Remove duplicates&lt;br /&gt;
		for k, v in pairs(t) do&lt;br /&gt;
			if not isNan(v) then&lt;br /&gt;
				-- NaNs cannot be table keys, and they are also unique so cannot be equal to anything in tn.&lt;br /&gt;
				exists[v] = true&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	local tn = select(lim, ...)&lt;br /&gt;
	checkType('valueComplement', lim, tn, 'table')&lt;br /&gt;
	tn = makeValueSet(tn) -- Remove duplicates&lt;br /&gt;
	for k, v in pairs(tn) do&lt;br /&gt;
		if isNan(v) or exists[v] == nil then&lt;br /&gt;
			ret[#ret + 1] = v&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return ret&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- symmDiff&lt;br /&gt;
--&lt;br /&gt;
-- This returns the symmetric difference of key/value pairs of t1, t2, ..., tn.&lt;br /&gt;
-- The symmetric difference of two tables consists of the key/value pairs&lt;br /&gt;
-- that appear in set 1 but not set 2, together with the key/value pairs that&lt;br /&gt;
-- appear in set 2 but not in set 1. This is the same as the union of the two&lt;br /&gt;
-- minus the intersection. If either of the tables contain different values for the&lt;br /&gt;
-- same table key, the table value is converted to an array holding all of the&lt;br /&gt;
-- different values.For more than two tables, this can get confusing - see the &lt;br /&gt;
-- &amp;quot;Symmetric difference&amp;quot; article for details.&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
--]]&lt;br /&gt;
&lt;br /&gt;
--[[ -- This is a rough work in progress.&lt;br /&gt;
function p.symmDiff(...)&lt;br /&gt;
	local lim = select('#', ...) &lt;br /&gt;
	if lim &amp;lt; 2 then&lt;br /&gt;
		error(&amp;quot;too few arguments to 'symmDiff' (minimum is 2, received &amp;quot; .. lim .. ')', 2)&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	local tremove = table.remove&lt;br /&gt;
	local trackArrays = {}&lt;br /&gt;
	&lt;br /&gt;
	local function symmDiffTwo(t1, t2)&lt;br /&gt;
		local ret = {}&lt;br /&gt;
		for k, v in pairs(t1) do&lt;br /&gt;
			local t2val = t2[k]&lt;br /&gt;
			if t2val == nil then&lt;br /&gt;
				ret[k] = v&lt;br /&gt;
			elseif trackArrays[k] then&lt;br /&gt;
				local array = ret[k]&lt;br /&gt;
				local valExists&lt;br /&gt;
				for i, arrayVal in ipairs(array) do&lt;br /&gt;
					if arrayVal == v then&lt;br /&gt;
						valExists = true&lt;br /&gt;
						break&lt;br /&gt;
					end&lt;br /&gt;
				end&lt;br /&gt;
				if not valExists then&lt;br /&gt;
					array[#array + 1] = v&lt;br /&gt;
				end&lt;br /&gt;
			elseif v ~= t2val then&lt;br /&gt;
				ret[k] = {t2val, v}&lt;br /&gt;
				trackArrays[k] = true&lt;br /&gt;
			end&lt;br /&gt;
--]]&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>Zoran</name></author>
	</entry>
</feed>