5

ruby スクリプトで大きな CSV ファイルを解析しており、いくつかの検索キーからタイトルに最も近いものを見つける必要があります。検索キーは 1 つ以上の値である可能性があり、以下のように値が正確に一致しない場合があります (近いはずです)。

search_keys = ["big", "bear"]

検索する必要があるデータを含む大きな配列で、列のみを検索したいtitle:

array = [
          ["id", "title",            "code", "description"],
          ["1",  "once upon a time", "3241", "a classic story"],
          ["2",  "a big bad wolf",   "4235", "a little scary"],
          ["3",  "three big bears",  "2626", "a heart warmer"]
        ]

["3", "three big bears", "2626", "a heart warmer"]この場合、これが検索キーに最も近い行を返すようにしたいと思います。

指定された検索キーから最も近い一致を返したい。

使用できるヘルパー/ライブラリ/宝石はありますか? 誰もこれを前にやった??

4

5 に答える 5

2

私が心配しているのは、このタスクをデータベースレベルまたは同様の検索エンジンで処理する必要があることです。アプリでデータを取得したり、列/行などを検索したりするのは無駄であり、費用がかかるはずです。しかし、今のところ、ここに単純なアプローチがあります:)

array = [
          ["id", "title",            "code", "description"],
          ["1",  "once upon a time", "3241", "a classic story"],
          ["2",  "a big bad wolf",   "4235", "a little scary"],
          ["3",  "three big bears",  "2626", "a heart warmer"]
        ]


h = {}

search_keys = ["big", "bear"]

array[1..-1].each do |rec|
  rec_id = rec[0].to_i

  search_keys.each do |key|
    if rec[1].include? key
      h[rec_id] = h[rec_id] ? (h[rec_id]+1) : 1
    end
  end
end

closest = h.keys.first

h.each do |rec, count| 
  closest = rec if h[closest] < h[rec]
end

array[closest] # => desired output :)
于 2012-05-30T08:30:02.570 に答える
1

自分でできるし、宝石を使う必要もないと思います!これはあなたが必要とするものに近いかもしれません。配列でキーを検索し、見つかった各要素のランクを設定します。

result = []
array.each do |ar|
    rank = 0
    search_keys.each do |key|
        if ar[1].include?(key)
            rank += 1
        end
    end

    if rank > 0
        result << [rank, ar]
    end 
end

このコードは上記よりもうまく書くことができますが、詳細をお見せしたいと思います。

于 2012-05-30T08:19:37.407 に答える
1

これが私のワンラインショットです

p array.find_all {|a|a.join.scan(/#{search_keys.join("|")}/).length==search_keys.length}
=>[["3", "three big bears", "2626", "a heart warmer"]]

一致数の順にすべての行を取得する

p array.drop(1).sort_by {|a|a.join.scan(/#{search_keys.join("|")}/).length}.reverse

最後のソリューションを組み合わせて、キーを含まない行を削除し、そのまま簡潔に保つ方法を知っている人はいますか?

于 2012-05-30T17:20:06.257 に答える
1

もっと簡潔に書けばいいのに…。

array = [
          ["id", "title",            "code", "description"],
          ["1",  "once upon a time", "3241", "a classic story"],
          ["2",  "a big bad wolf",   "4235", "a little scary"],
          ["3",  "three big bears",  "2626", "a heart warmer"]
        ]
search_keys = ["big", "bear"]


def sift(records, target_field, search_keys)
    # find target_field index
    target_field_index = nil
    records.first.each_with_index do |e, i|
        if e == target_field
            target_field_index = i
            break
        end
    end
    if target_field_index.nil?
        raise "Target field was not found"
    end

    # sums up which records have a match and how many keys they match
    # key => val = record => number of keys matched
    counter = Hash.new(0) # each new hash key is init'd with value of 0

    records.each do |record| # look at all our given records
        search_keys.each do |key| # check each search key on the field
            if record[target_field_index].include?(key)
                counter[record] += 1 # found a key, init to 0 if required and increment count
            end
        end
    end

    # find the result with the most search key matches
    top_result = counter.to_a.reduce do |top, record|
        if record[1] > top[1] # [0] = record, [1] = key hit count
            top = record # set to new top
        end
        top # continue with reduce
    end.first # only care about the record (not the key hit count)
end


puts "Top result: #{sift array, 'title', search_keys}"
# => Top result: ["3", "three big bears", "2626", "a heart warmer"]
于 2012-05-30T09:43:44.217 に答える
1

これは機能します。一致した* 行の配列を検索して返しますresult

*一致した行 = ID、タイトル、コード、または説明が提供された検索キーのいずれかに一致する行。「クマ」の「クマ」などの部分検索を含む

result = []
array.each do |a|
    a.each do |i|
        search_keys.each do |k|
            result << a if i.include?(k)
        end
    end
end
result.uniq!
于 2012-05-30T09:29:10.377 に答える