<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://moasspedia.org/w/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://moasspedia.org/w/index.php?action=history&amp;feed=atom&amp;title=Module%3ASet"/>
	<link rel="alternate" type="text/html" href="https://moasspedia.org/w/index.php?title=Module:Set&amp;action=history"/>
	<updated>2026-04-15T18:06:06Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.37.2</generator>
	<entry>
		<id>https://moasspedia.org/w/index.php?title=Module:Set&amp;diff=3324&amp;oldid=prev</id>
		<title>Wikipedia&gt;Andrybak: Reverted to revision 994891575 by Awesome Aasim (talk)</title>
		<link rel="alternate" type="text/html" href="https://moasspedia.org/w/index.php?title=Module:Set&amp;diff=3324&amp;oldid=prev"/>
		<updated>2021-01-23T09:48:08Z</updated>

		<summary type="html">&lt;p&gt;Reverted to revision 994891575 by &lt;a href=&quot;/wiki/Special:Contributions/Awesome_Aasim&quot; title=&quot;Special:Contributions/Awesome Aasim&quot;&gt;Awesome Aasim&lt;/a&gt; (&lt;a href=&quot;/w/index.php?title=User_talk:Awesome_Aasim&amp;amp;action=edit&amp;amp;redlink=1&quot; class=&quot;new&quot; title=&quot;User talk:Awesome Aasim (page does not exist)&quot;&gt;talk&lt;/a&gt;)&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(&amp;#039;libraryUtil&amp;#039;)&lt;br /&gt;
local checkType = libraryUtil.checkType&lt;br /&gt;
local tableTools = require(&amp;#039;Module:TableTools&amp;#039;)&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&amp;#039;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&amp;#039;t be table keys, so don&amp;#039;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(&amp;#039;#&amp;#039;, ...) &lt;br /&gt;
	if lim &amp;lt; 2 then&lt;br /&gt;
		error(&amp;quot;too few arguments to &amp;#039;union&amp;#039; (minimum is 2, received &amp;quot; .. lim .. &amp;#039;)&amp;#039;, 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(&amp;#039;union&amp;#039;, i, t, &amp;#039;table&amp;#039;)&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(&amp;#039;#&amp;#039;, ...) &lt;br /&gt;
	if lim &amp;lt; 2 then&lt;br /&gt;
		error(&amp;quot;too few arguments to &amp;#039;valueUnion&amp;#039; (minimum is 2, received &amp;quot; .. lim .. &amp;#039;)&amp;#039;, 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(&amp;#039;valueUnion&amp;#039;, i, t, &amp;#039;table&amp;#039;)&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(&amp;#039;#&amp;#039;, ...) &lt;br /&gt;
	if lim &amp;lt; 2 then&lt;br /&gt;
		error(&amp;quot;too few arguments to &amp;#039;intersection&amp;#039; (minimum is 2, received &amp;quot; .. lim .. &amp;#039;)&amp;#039;, 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(&amp;#039;intersection&amp;#039;, i, t, &amp;#039;table&amp;#039;)&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(&amp;#039;#&amp;#039;, ...) &lt;br /&gt;
	if lim &amp;lt; 2 then&lt;br /&gt;
		error(&amp;quot;too few arguments to &amp;#039;valueIntersection&amp;#039; (minimum is 2, received &amp;quot; .. lim .. &amp;#039;)&amp;#039;, 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(&amp;#039;valueIntersection&amp;#039;, i, t, &amp;#039;table&amp;#039;)&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&amp;#039;t be in the intersection.&lt;br /&gt;
			-- Which is lucky, as they also can&amp;#039;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(&amp;#039;#&amp;#039;, ...) &lt;br /&gt;
	if lim &amp;lt; 2 then&lt;br /&gt;
		error(&amp;quot;too few arguments to &amp;#039;complement&amp;#039; (minimum is 2, received &amp;quot; .. lim .. &amp;#039;)&amp;#039;, 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&amp;#039;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(&amp;#039;complement&amp;#039;, lim, tn, &amp;#039;table&amp;#039;)&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(&amp;#039;complement&amp;#039;, i, t, &amp;#039;table&amp;#039;)&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(&amp;#039;#&amp;#039;, ...) &lt;br /&gt;
	if lim &amp;lt; 2 then&lt;br /&gt;
		error(&amp;quot;too few arguments to &amp;#039;valueComplement&amp;#039; (minimum is 2, received &amp;quot; .. lim .. &amp;#039;)&amp;#039;, 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(&amp;#039;valueComplement&amp;#039;, i, t, &amp;#039;table&amp;#039;)&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(&amp;#039;valueComplement&amp;#039;, lim, tn, &amp;#039;table&amp;#039;)&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(&amp;#039;#&amp;#039;, ...) &lt;br /&gt;
	if lim &amp;lt; 2 then&lt;br /&gt;
		error(&amp;quot;too few arguments to &amp;#039;symmDiff&amp;#039; (minimum is 2, received &amp;quot; .. lim .. &amp;#039;)&amp;#039;, 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>Wikipedia&gt;Andrybak</name></author>
	</entry>
</feed>