鉴于字典,我的程序会生成两个输出文件,' sequences.txt'和' words.txt'。
例如,给定spec/fixtures/sample_words.txt
字典仅包含
arrows
carrots
give
me
输出应为:
'sequences' 'words'
carr carrots
give give
rots carrots
rows arrows
rrot carrots
rrow arrows
当然,' arro'因为它不会出现在输出中 发现不止一个字。
项目结构:
├── Gemfile
├── Gemfile.lock
├── examples
│ └── dictionary.txt
├── lib
│ └── word_sequence_parser.rb
├── main.rb
├── output
├── readme.md
└── spec
├── fixtures
│ └── sample_words.txt
└── word_sequence_parser_spec.rb
运行脚本:
ruby main.rb examples/dictionary.txt
main.rb的
require_relative 'lib/word_sequence_parser.rb'
dict_path = ARGV.shift
if dict_path.nil?
dict_path = 'spec/fixtures/sample_words.txt'
end
parser = WordSequenceParser.new(dict_path)
# step 1 - Opens dictionary file and generates a new set of words
parser.set
# step 2 - Parses word sequences
parser.sequence
# step 3 - Prints to files in ./output
parser.dump_text
word_sequence_parser.rb
require 'set'
class WordSequenceParser
def initialize(path)
@path = path
end
def set
set = Set.new
File.open(@path) do |f|
f.each_line do |line|
set.add(line.chomp.downcase)
end
end
set
end
def sequence
sequences = Set.new
words = Set.new
to_remove = Set.new
set.each do |w|
letters = w.split(//)
letters.each_cons(4) do |seq|
s = seq.join
if !words.add?(s)
to_remove.add(s)
end
sequences.add( {seq: s, word: w} )
end
end
sequences.delete_if { |hash| to_remove.include?(hash[:seq]) }
end
def dump_text
output_s = File.open( 'output/sequences.txt', 'w' )
output_w = File.open( 'output/words.txt', 'w' )
sequence.each do |hash|
output_s.puts("#{hash[:seq]}")
output_w.puts("#{hash[:word]}")
end
output_s.close
output_w.close
end
end
require 'set'
class WordSequenceParser
def initialize(path)
@path = path
end
def set
set = Set.new
File.open(@path) do |f|
f.each_line do |line|
set.add(line.chomp.downcase)
end
end
set
end
def memoize
@set = set
end
def sequence
sequences = Set.new
words = Set.new
to_remove = Set.new
@set.each do |w|
letters = w.split(//)
letters.each_cons(4) do |seq|
s = seq.join
if !words.add?(s)
to_remove.add(s)
end
sequences.add( {seq: s, word: w} )
end
end
sequences.delete_if { |hash| to_remove.include?(hash[:seq]) }
end
def dump_text
output_s = File.open( 'output/sequences.txt', 'w' )
output_w = File.open( 'output/words.txt', 'w' )
sequence.each do |hash|
output_s.puts("#{hash[:seq]}")
output_w.puts("#{hash[:word]}")
end
output_s.close
output_w.close
end
end
尝试运行脚本时收到此错误消息。
../word_sequence_parser.rb:29:in `sequence': undefined method `each' for nil:NilClass (NoMethodError)
from main.rb:15:in `<main>'
我已经阅读了Justin Weiss' article on memoization,并且大部分内容得到了它。只是很难将这种技术应用到我已经写过的东西中。
答案 0 :(得分:1)
它不起作用,因为你从不调用memoize,所以@set永远不会被初始化。
然而,真正的问题在于,没有什么值得记住的。
您的原始代码看起来非常好,如果您考虑它是如何工作的,那么就不是任何代码的冗余执行。执行一次或多次执行的每一行都会返回不同的值。
因此,记忆中没有任何目的。
让我们说你想多次调用dump_text(或只是序列)然后你肯定想要按如下方式记忆序列:
def sequence
@sequence ||= begin
sequences = Set.new
words = Set.new
to_remove = Set.new
set.each do |w|
letters = w.split(//)
letters.each_cons(4) do |seq|
s = seq.join
if !words.add?(s)
to_remove.add(s)
end
sequences.add( {seq: s, word: w} )
end
end
sequences.delete_if { |hash| to_remove.include?(hash[:seq]) }
end
end
这只会执行一次原始序列计算代码,然后分配@sequence。每次对@sequence的调用都将重用已经计算过的@sequence的值(因为它现在不是nil。)
我喜欢这个问题,因为当我的公司开始使用ruby时,这是我记得的第一件事。我们有一位顾问重做了很多旧的asp.net代码,他在方法中有这些@foo || = ...表达式,这是我以前从未见过的。