Reputation: 1259
I have two huge arrays of sentences, one in German and one in English. I will search through the German sentences for sentences that contain a certain word and if they do, I will check if there is an equivalent English sentence (using a hash with connection information). However, if the user is looking for a very common word, I don't want to return every single sentence that contains it but only the first x matches and stop searching then.
If I do german_sentences.index { |sentence| sentence.include?(word) }
I get only one match at a time.
If I use german_sentences.keep_if { |sentence| sentence.include?(word) }
I get all matches, but also lose the index information, which is really critical for this.
I am now using a custom loop with each_with_index and break once the maximum has been reached, but I really feel that I must be missing some existing solution, at least something that gives a limited number of matches (even if not their indices)...
Upvotes: 2
Views: 133
Reputation: 110665
If your need is not a one-off, you could use Module#refine, rather than monkeypatching Array
). refine
was added to v2.0 experimentally, then changed considerably in v. 2.1. One of the restrictions in the use of refine is: "You may only activate refinements at top-level...", which evidently prevents testing in Pry and IRB.
module M
refine Array do
def select_indices_first(n)
i = 0
k = 0
a = []
return a if n == 0
each { |x| (a << i; k += 1) if yield(x); break if k == n; i += 1 }
a
end
def select_first(n) # if you wanted this also...
k = 0
a = []
return a if n == 0
each { |x| (a << x; k += 1) if yield(x); break if k == n }
a
end
end
end
using M
sentences = ["How now brown", "Cat", "How to guide", "How to shop"]
sentences.select_indices_first(0) {|s| s.include?("How")} # => []
sentences.select_indices_first(1) {|s| s.include?("How")} # => [0]
sentences.select_indices_first(2) {|s| s.include?("How")} # => [0, 2]
sentences.select_indices_first(3) {|s| s.include?("How")} # => [0, 2, 3]
sentences.select_indices_first(99) {|s| s.include?("How")} # => [0, 2, 3]
sentences.select_first(2) {|s| s.include?("How")}
# => ["How now brown", "How to guide"]
Upvotes: 1
Reputation: 168081
german_sentences
.each_index
.lazy
.select{|i| german_sentences[i].include?(word)}
.first(n)
Upvotes: 4