h = {}
File.open("candidates.txt").each do |line|
  line.chomp!
  name,val = line.split(",")
  name.downcase!
  h[name] ||= 0.0  # create an entry if it doesn't exist.
  h[name] += val.to_f # val is a float
end
File.open("all.txt").each do |line|
  line.chomp!
  name,val1,val2 = line.split(",")
  name = name.downcase!
  
  next if not h[name] # only from candidates
  
  puts [name,h[name],val1,val2].join("\t")
end
import tables, strutils
var tab = initTable[string, float]()
for line in lines("candidates.txt"):
  let
    ln = line.split(',')
    name = ln[0].toLower
    val = ln[1].parseFloat
  
  if not tab.hasKey(name): tab[name] = 0.0
  tab.mget(name) += val
for line in lines("all.txt"):
  let
    ln = line.split(',')
    name = ln[0].toLower
  
  if not tab.hasKey(name):
    continue # ruby next
  
  let
    val1 = ln[1].parseFloat
    val2 = ln[2].parseFloat
  
  echo "$#\t$#\t$#\t$#".format(
    name, tab[name], val1, val2 )
Thanks fowl!
I had a bug in the ruby version.
replace: name = name.downcase! with with: name.downcase! The nimrod version takes 11 seconds vs 25 seconds for the ruby version (4 million lines in candidates.txt and 6 million in all.txt). compiled with -d:release Nice! I have a feeling it's going to be a nimrod weekend :-)
@joe: Keep in mind that a program such as the above is mainly IO bound, both hard-disk wise and memory-wise. Thus it will take a certain amount of constant time for a program like the above, written in any language, to run.
When I test such things, I generally load the entire set of files I'm working on into memory with a RAM disk program. The IO speed of random access memory is much faster than that of mechanical hard disks.