然后根据字符串输入搜索排序数组

时间:2012-05-09 17:27:00

标签: ruby

如何改进此排序方法以满足以下条件:

  • 首先返回完全匹配
  • 部分匹配遵循完全匹配
def find_me
  records = ["gogol", "garrison", "feathers", "grains"]
  sorted = []   

  print "what are you looking for? "
  term = gets.chomp.downcase    

  records.select do |record|
    if term == record.downcase
      #exact match
      sorted << record
    elsif  term[0] == record[0] or term[1] == record[1] or term[2] == record[2]
      #if the first three chars match add it
      sorted << record
    end
  end

  sorted.sort! {|b| term <=> b }
end

2 个答案:

答案 0 :(得分:2)

def find_me
  records = ["gogol", "garrison", "feathers", "grains"]
  exact_matches   = []
  partial_matches = []  

  print "what are you looking for? "
  term = gets.chomp.downcase    

  records.each do |record|
    if term == record.downcase
      #exact match
      exact_matches << record
    elsif  term.slice(0, 3) == record.slice(0, 3)
      #if the first three chars match add it
      partial_matches << record
    end
  end

  # Just add the Arrays and it'll put the exact matches first and the 
  # partial ones last without a need for sorting. =)
  sorted = exact_matches + partial_matches 
end

答案 1 :(得分:1)

您可以记下哪些是完全匹配,哪些是完整匹配:

matches = records.each_with_object([]) do |record, m|
  if term == record.downcase
    m << [ 0, record ]
  elsif term[0, 3] == record[0, 3]
    m << [ 1, record ]
  end
end

然后对两个值进行排序并解压缩内部数组:

matches.sort.map(&:last)

我不确定你期望这样做:

sorted.sort! {|b| term <=> b }

但它会因为sort块应该阵列的两个元件相互比较做奇怪的事情和你&#39;再完全无视第二个;例如,这发生在我身上:

>> [4,2,1,2,4].sort { |x| 3 <=> x }
=> [4, 4, 1, 2, 2]

并且由此产生的排序没有多大意义。


each_with_object一次做几件事:

  1. 找到完全匹配并将其标记为完全匹配(前导0)。
  2. 找到前缀匹配并将其标记为部分匹配(前导1)。
  3. 返回要存储在matches中的组合列表; e.each_with_object(m)m作为第二个参数传递给块,并返回m
  4. 这会留下matches,如下所示:

    [ [0, a], [1, b], [1, c], ... ]
    

    前导0表示完全匹配,1表示前缀匹配。然后你可以让sort正常排序matches,因为Array#<=>逐个元素地比较数组; 0在1之前,所以完全匹配最终成为第一。然后我们可以使用map丢弃确切/部分指标,在每个内部数组上调用last