我目前正在研究街道名称的自动填充算法。 我得到一个文件作为参数,这是我的地址格式:
City,<SPACE>StreetNumber<SPACE>StreetName\n
城市和街道名称可以完整的单词填写(所以如果城市是“拉罗谢尔”,如果读“L”或“R”,算法应显示“La Rochelle”)
我当时从STDIN 1字符获得用户输入。
如果你不理解,这里有一些例子:
/B-ADM-442> ./autoCompletion exampleDict 2>\dev\null < test2
l
i
v
2
/B-ADM-442> ./autoCompletion exampleDict 2>\dev\null < test2
{m} {l} {p} {s} {d}
{Li} {Ly}
{LILLE, d} {LILLE, v} {LILLE, g} {LILLE, h} {LILLE, p}
{1 : LILLE, 30 rue VICTOR danel} {2 : LILLE, 120 boulevard VICTOR hugo}
=> Lille, 120 boulevard Victor Hugo
目前我只能完成城市所以“LILLE”,但现在我有点卡住了,我不知道怎么做其余的完整。
如果您有一些问题,请不要犹豫。
到目前为止,这是我的代码,它有点大,但我有点像红宝石菜鸟:)
#!/usr/bin/env ruby
#coding: utf-8
require 'set'
## ___________ _____ _____
## |_ _| ___ \_ _| ___|
## | | | |_/ / | | | |__
## | | | / | | | __|
## | | | |\ \ _| |_| |___
## \_/ \_| \_|\___/\____/
##
class Trie
attr_accessor :children, :value, :flag
def initialize value=nil
@children = {}
@value = value
@flag = false
end
def add char
val = value ? value + char : char
children[char] = Trie.new val
end
def insert word
node = self
word.each_char do |char|
node.add char if not node.children.has_key? char
node = node.children[char]
end
node.flag = true
end
def find word
node = self
word.each_char do |char|
return nil if not node.children.has_key? char
node = node.children[char]
end
return node.value
end
def all_prefixes
results = Set.new
results.add value if flag
return results if children.empty?
ap = children.values.collect {|node| node.all_prefixes}
reduced = ap.reduce {|a,b| a.merge b}
reduced or results
end
def autocomplete prefix
node = self
prefix.each_char do |char|
return Set.new if not node.children.has_key? char
node = node.children[char]
end
return node.all_prefixes
end
end
## ______ _____ _____ _____ _____ _____ _ _ _ _ ___ ________ __
## | _ \_ _/ __ \_ _|_ _| _ | \ | || \ | | / _ \ | ___ \ \ / /
## | | | | | | | / \/ | | | | | | | | \| || \| |/ /_\ \| |_/ /\ V /
## | | | | | | | | | | | | | | | | . ` || . ` || _ || / \ /
## | |/ / _| |_| \__/\ | | _| |_\ \_/ / |\ || |\ || | | || |\ \ | |
## |___/ \___/ \____/ \_/ \___/ \___/\_| \_/\_| \_/\_| |_/\_| \_| \_/
##
class Dictionnary
def initialize file, trieCity, trieStreet
@validLine = /[a-zA-ZáàâäãåçéèêëíìîïñóòôöõúùûüýÿæœÁÀÂÄÃÅÇÉÈÊËÍÌÎÏÑÓÒÔÖÕÚÙÛÜÝŸÆŒ' ._-]+, \d+ [a-zA-Z0-9áàâäãåçéèêëíìîïñóòôöõúùûüýÿæœÁÀÂÄÃÅÇÉÈÊËÍÌÎÏÑÓÒÔÖÕÚÙÛÜÝŸÆŒ' ._-]+/
@streetTypes = Array["allée", "avenue", "boulevard", "chemin", "impasse", "place", "quai", "rue", "square"]
@regCity = /[a-zA-ZáàâäãåçéèêëíìîïñóòôöõúùûüýÿæœÁÀÂÄÃÅÇÉÈÊËÍÌÎÏÑÓÒÔÖÕÚÙÛÜÝŸÆŒ' ._-]+/
@regStreetName = /[a-zA-ZáàâäãåçéèêëíìîïñóòôöõúùûüýÿæœÁÀÂÄÃÅÇÉÈÊËÍÌÎÏÑÓÒÔÖÕÚÙÛÜÝŸÆŒ' ._-]+, \d+ ([a-zA-Z0-9áàâäãåçéèêëíìîïñóòôöõúùûüýÿæœÁÀÂÄÃÅÇÉÈÊËÍÌÎÏÑÓÒÔÖÕÚÙÛÜÝŸÆŒ' ._-]+)/
@regStreetNumber = /[a-zA-ZáàâäãåçéèêëíìîïñóòôöõúùûüýÿæœÁÀÂÄÃÅÇÉÈÊËÍÌÎÏÑÓÒÔÖÕÚÙÛÜÝŸÆŒ' ._-]+, (\d+) [a-zA-Z0-9áàâäãåçéèêëíìîïñóòôöõúùûüýÿæœÁÀÂÄÃÅÇÉÈÊËÍÌÎÏÑÓÒÔÖÕÚÙÛÜÝŸÆŒ' ._-]+/
@trieCity = trieCity
@trieStreet = trieStreet
@trieLine = Trie.new
@f_letter = Array.new
@city = String.new
@street = String.new
@cityComplete = false
begin
@file = File.new(file.to_s, "r")
rescue => err
puts "Invalid argument"
exit 84
end
counter = 0
while line = @file.gets
if @validLine.match(line)
line[@regCity].split.each {|words| @f_letter.push(words.downcase)}
line[@regCity].split.each {|words| @trieCity.insert(words.downcase)}
street = line.scan(@regStreetName).to_s.split[0].match(@regCity)
@trieStreet.insert(line.scan(@regStreetName).last.first)
end
counter += 1
end
if counter == 0
puts "Invalid argument"
exit 84
end
end
def prompt
hash = @f_letter.each.each_with_object(Hash.new(0)) {|word, hsh| hsh[word[0].downcase] += 1}
hash = Hash[hash.sort_by {|k, v| [-v, k] }]
counter = 1
hash.each do |k, _|
print "{#{k}}"
if counter < 5 && counter < hash.size
print " "
else
print "\n"
break
end
counter += 1
end
end
def handle_input char
if @cityComplete == false
self.complete_city(char)
else
self.complete_street(char)
end
end
def complete_city char
@city.insert(@city.size, char)
array = @trieCity.autocomplete(@city)
if array.size == 1
@city = array.first.dup
@cityComplete = true
return
end
counter = 1
array.each do |word|
print "{#{word.chars.first((@city.size) + 1).join.capitalize}}"
if counter < 5 && counter < array.size
print " "
else
print "\n"
break
end
counter += 1
end
end
def complete_street char
puts @city
puts char
@street.insert(@street.size, char)
array = @trieStreet.autocomplete(@street)
puts array.inspect
end
end
## ___________ _____ _____ _____ _ _ _____
## | _ | ___ \_ _|_ _| _ | \ | |/ ___|
## | | | | |_/ / | | | | | | | | \| |\ `--.
## | | | | __/ | | | | | | | | . ` | `--. \
## \ \_/ / | | | _| |_\ \_/ / |\ |/\__/ /
## \___/\_| \_/ \___/ \___/\_| \_/\____/
if !ARGV[0]
puts "Invalid argument"
exit 84
end
if ARGV[0] == "-h"
puts "USAGE"
puts "\t./autocompletion dictionnary\n\n"
puts "DESCRIPTION"
puts "\tdictionnary\tfile, containing one address per line, serving as knowledge base"
exit 0
end
## ___ ___ ___ _____ _ _
## | \/ | / _ \|_ _| \ | |
## | . . |/ /_\ \ | | | \| |
## | |\/| || _ | | | | . ` |
## | | | || | | |_| |_| |\ |
## \_| |_/\_| |_/\___/\_| \_/
trie1 = Trie.new
trie2 = Trie.new
dictionnary = Dictionnary.new(ARGV[0], trie1, trie2)
dictionnary.prompt
while user_input = STDIN.gets
user_input ||= ''
user_input.chomp!
case user_input
when "ABORT"
exit 0
else
if user_input.size > 1
exit 84
end
dictionnary.handle_input(user_input[0])
end
end
谢谢, 托马斯
答案 0 :(得分:0)
为了帮助您入门,请查看readlines,并结合使用abbrev(均来自标准库)。
require "abbrev"
require "readline"
arr = ["Marseille", "Marsan", "Martin"]
Readline.completion_proc = arr.abbrev.to_proc
while buffer = Readline.readline(">", true) # true means: keep history.
exit if buffer.strip == "quit"
p buffer
end