Hash join: Difference between revisions

2,445 bytes added ,  3 years ago
Line 1,717:
</pre>
=={{header|Lua}}==
===Literal===
Lua tables are implemented with hash keys, so this task is a bit anti-idiomatic for Lua. That is, if you knew in advance that this would be the primary operation on the data, then you'd likely (re-)structure the data to directly support it. But, to comply with the intent of the task, the data here is initially structured as an indexed (rather than hash-keyed) array, <i>then</i> hashed dynamically. (it's analogous to the Python solution, where a list is immediately converted to a dictionary - but could have <i>began</i> as a dictionary)
<lang lua>local function recA(age, name) return { Age=age, Name=name } end
Line 1,749 ⟶ 1,750:
28 Alan Alan Zombies
28 Glory Glory Buffy</pre>
===Idiomatic===
Or, at least semi-idiomatic / more-idiomatic, per comments above under the "Literal" implementation. Here, a "hashlist" structure is defined to allow retrieval either by indexed-list style (the database "rows") or by hashed-array-of-lists style (the database "index"), where the hash is maintained upon insert so that a later "hashjoin" operation becomes just a "join" operation. (Note that storage/performance issues are minimal, at least at this scale, as both the keys and rows in the hash are merely references, not copies.)
<lang lua>local hashlist = {
new = function(self,key)
return setmetatable({key=key, hash={}, list={}}, {__index=self})
end,
insert = function(self,row)
self.list[#self.list+1] = row
if not self.hash[row[self.key]] then self.hash[row[self.key]]={} end
table.insert(self.hash[row[self.key]], row)
return self
end,
join = function(self,tabb)
local result = {}
for _,rowb in pairs(tabb.list) do
if (self.hash[rowb[tabb.key]]) then
for _,rowa in pairs(self.hash[rowb[tabb.key]]) do
result[#result+1] = { A=rowa, B=rowb }
end
end
end
return result
end
}
 
local function recA(age, name) return { Age=age, Name=name } end
tabA = hashlist:new("Name")
:insert(recA(27,"Jonah"))
:insert(recA(18,"Alan"))
:insert(recA(28,"Glory"))
:insert(recA(18,"Popeye"))
:insert(recA(28,"Alan"))
 
local function recB(character, nemesis) return { Character=character, Nemesis=nemesis } end
local tabB = hashlist:new("Character")
:insert(recB("Jonah","Whales"))
:insert(recB("Jonah","Spiders"))
:insert(recB("Alan","Ghosts"))
:insert(recB("Alan","Zombies"))
:insert(recB("Glory","Buffy"))
 
for _,row in pairs(tabA:join(tabB)) do
print(row.A.Age, row.A.Name, row.B.Character, row.B.Nemesis)
end
print("or vice versa:")
for _,row in pairs(tabB:join(tabA)) do
print(row.B.Age, row.B.Name, row.A.Character, row.A.Nemesis)
end</lang>
{{out}}
<pre>27 Jonah Jonah Whales
27 Jonah Jonah Spiders
18 Alan Alan Ghosts
28 Alan Alan Ghosts
18 Alan Alan Zombies
28 Alan Alan Zombies
28 Glory Glory Buffy
or vice versa:
27 Jonah Jonah Whales
27 Jonah Jonah Spiders
18 Alan Alan Ghosts
18 Alan Alan Zombies
28 Glory Glory Buffy
28 Alan Alan Ghosts
28 Alan Alan Zombies</pre>
 
=={{header|LFE}}==
Anonymous user