You can do this in Ruby with very little code. Here's one way:
DICT_FNAME = "#{path}" + "dictionary.txt"
NEW_DICT_FNAME = "#{path}" + "new_dictionary.txt"
PREP_FNAME = "#{path}" + "prepositions.txt"
all_words = File.read(DICT_FNAME).split($/).map(&:strip)
prepositions = File.read(PREP_FNAME).split($/).map(&:strip)
File.write(NEW_DICT_FNAME, (all_words - prepositions).join($/))
puts "#{all_words.size} words in the dictionary"
puts "#{prepositions.size} prepositions to be removed"
Let's try it out. First, write some words to the dictionary file and to the file containing the prepositions:
all = <<_
Now
is
the
time
for
all
Rubyists
to
debug
_
preps = <<_
for
to
_
all #=> "Now\nis\nthe\ntime\nfor\nall\nRubyists\nto\ndebug\n"
preps #=> "for\nto\n"
path = ''
DICT_FNAME = "#{path}" + "dictionary.txt" #=> "dictionary.txt"
PREP_FNAME = "#{path}" + "prepositions.txt" #=> "prepositions.txt"
File.write(DICT_FNAME, all) #=> 42
File.write(PREP_FNAME, preps) #=> 7
Now we read the two input files [$/
is the end-of-line character(s)]:
NEW_DICT_FNAME = "#{path}" + "new_dictionary.txt"
all_words = File.read(DICT_FNAME).split($/).map(&:strip)
#=> ["Now", "is", "the", "time", "for", "all", "Rubyists", "to", "debug"]
prepositions = File.read(PREP_FNAME).split($/).map(&:strip)
#=> ["for", "to"]
puts "#{all_words.size} words in the dictionary"
#=> 9 words in the dictionary
puts "#{prepositions.size} prepositions to be removed"
#=> 2 prepositions to be removed
...then remove the elements of the prepositions
array from the all_words
array:
diff = all_words - prepositions
#=> ["Now", "is", "the", "time", "all", "Rubyists", "debug"]
...format it for writing:
joined = diff.join($/)
#=> "Now\nis\nthe\ntime\nall\nRubyists\ndebug"
...write the output file:
File.write(NEW_DICT_FNAME, joined)
...and confirm it it was written correctly:
File.read(NEW_DICT_FNAME).split($/).map(&:strip)
#=> ["Now", "is", "the", "time", "all", "Rubyists", "debug"]
Edit: In view of @Tokland's suggestion of constructing a set of prepositions when processing the words one at a time, I thought it might be interesting to run some benchmarks. You'll see that I just used random arrays and words, rather than read and write to files.
L = Array('a'..'z')
require 'set'
def make_samples(n,m,k,s)
s.times.with_object([]) do |_,a|
# Construct a sample of n unique words, each of length k
all_words = make_sample(n,k)
# Assume the first m words are prepositions
preps = all_words[0,m]
# Shuffle the words (no need to further randomize the prepositions)
a << [all_words.shuffle, preps]
end
end
def make_sample(n,k)
set_words = Set.new
while set_words.size < n do
set_words << k.times.with_object('') { |_,w| w << L.sample }
end
set_words.to_a
end
Here is an example of test data with 8 4-character words, of which 3 are prepositions, and a sample size of 2.
make_samples(8,3,4,2)
#=> [[["fexz", "gxrv", "acte", "namz", "cpqw", "txsm", "zonm", "tvjz"],
# ["zonm", "gxrv", "fexz"]],
# [["nfdf", "djnv", "inqk", "tbgc", "asfb", "nqbg", "dnyb", "ywtv"],
# ["djnv", "tbgc", "inqk"]]]
These are the parameters I used for the results I report below:
n = 200_000 # number of words, inckluding prepositions
m = 40 # number of prepositions
k = 8 # length of each string
s = 20 # sample size
samples = make_samples(n,m,k,s)
Benchmark.bm('reject - arr'.size) do |bm|
# words array - preps array
bm.report 'arr - arr' do
samples.each { |(wa,pa)| wa - pa }
end
# reject words in preps array
bm.report 'reject - arr' do
samples.each { |(wa,pa)| wa.reject { |w| pa.include? w } }
end
# reject words in preps set
bm.report 'reject - set' do
samples.each { |(wa,pa)| ps = pa.to_set; wa.reject { |w| ps.include? w } }
end
end
user system total real
arr - arr 0.860000 0.030000 0.890000 ( 0.884945)
reject - arr 10.180000 0.020000 10.200000 ( 10.217233)
reject - set 1.830000 0.040000 1.870000 ( 1.913069)
I ran a few additional tests with different parameters, but these results are indicative.