Basically, this code takes a keyword and an array of strings, then sorts them based on two things: the number of characters shared with the key, and the distance between them.(As a side note, would this properly be called a sort, not a search?)
def search(key, list)
# Format for everything pushed to out:
# Should this be a class?
# {
# val: the string in question,
# shared_chars: [{char: shared char of key list elem,
# index: index of shared char,
# kindex: index of shared char in key
# distance: how close the shared chars are}]
# }
out = []
key = key.downcase
list.each { |l|
l.downcase!
shared_chars = []
keyi = 0
key.each_char { |c|
index = /#{c}/ =~ l
if index != nil
shared_chars.push char: c, index: index, kindex: keyi
end
# Inelegant?
keyi += 1
}
# Calulate total distance between shared_chars
distance = 0
odistance = 0
shared_chars.each_index { |i|
unless i == shared_chars.length-1
distance += (shared_chars[i+1][:index] - shared_chars[i][:index]).abs
odistance += (shared_chars[i+1][:kindex] - shared_chars[i][:kindex]).abs
end
}
distance -= odistance
distance = distance.abs
out.push val: l, shared_chars: shared_chars, distance: distance
}
out.sort_by! { |e|
# 100 is arbitrary
100 + e[:distance] - e[:shared_chars].length*3
}
out
end
Specifically I would like to know if any part of it could be made more efficient and/or elegant, but general critique is of course welcome.