如何将字符串转换为数组的名称?
How do I turn a string into the name of an array?
我想我已经从字符串创建了多个数组,但如果我尝试检查数组,我会收到错误消息。
File.open("livestock.txt", "r") do |file|
file.readlines.each do |x|
if x.match(/:*:/)
# puts x.inspect
# strip string
x.gsub!(/[^A-Za-z]/, '')
x.downcase!
puts x.inspect
x = Array.new(){Hash.new}
# puts x.inspect
pigs.inspect
else
# puts "no"
end
end
end
animals.rb:12:in `block (2 levels) in <main>': undefined local variable or method `pigs' for main:Object (NameError)
from animals.rb:2:in `each'
from animals.rb:2:in `block in <main>'
from animals.rb:1:in `open'
from animals.rb:1:in `<main>'
理想情况下我想创造猪=[]
然后将哈希添加到此数组,例如:
pigs = [{"name"=>"peggy", "id"=>1, "owner"=>"wolcott farms"},
{"name"=>"sue", "id"=>2, "owner"=>"blue moon farms"},
{"name"=>"eddie", "id"=>3, "owner"=>"sunrise farms"}
]
奶牛等也是如此
我的文本文件 animals.txt 是
::pigs::
name, id, owner
peggy, 1, wolcott farms
sue, 2, blue moon farms
eddie, 3, sunrise farms
::cows::
name, id, owner
dee, 3, black hat farms
sunny, 2, blue moon farms
bess, 4, wolcott farms
自 Ruby v1.8 以来,无法创建局部变量。实例变量,是(使用Object#instance_variable_set),局部变量,否
@CodeGnome 给出了一种创建具有给定名称的实例变量的方法。然而,我不认为实例变量的集合是合适的数据结构。我建议您考虑改用哈希。您可以按如下方式进行。
代码
def doit(fname)
File.read(fname).
split(/\n{2,}/). # split paragraphs
each_with_object({}) do |s,h|
outer_key, inner_key_names, *inner_values = s.split(/\n/)
inner_keys = inner_key_names.split(/,\s+/)
h[outer_key[/(?<=::)[^:]+/]] =
inner_values.each_with_object([]) { |values_str, a|
a << inner_keys.zip(values_str.split(/,\s+/)).to_h }
end
end
例子
首先让我们创建您的文件。
FName = "animals.txt"
data =<<_
::pigs::
name, id, owner
peggy, 1, wolcott farms
sue, 2, blue moon farms
eddie, 3, sunrise farms
::cows::
name, id, owner
dee, 3, black hat farms
sunny, 2, blue moon farms
bess, 4, wolcott farms
_
File.write(FName, data)
#=> 203
现在在此文件上执行该方法。
doit(FName)
#=> {"pigs"=>[{"name"=>"peggy", "id"=>"1", "owner"=>"wolcott farms "},
# {"name"=>"sue", "id"=>"2", "owner"=>"blue moon farms"},
# {"name"=>"eddie", "id"=>"3", "owner"=>"sunrise farms"}],
# "cows"=>[{"name"=>"dee", "id"=>"3", "owner "=>"black hat farms "},
# {"name"=>"sunny", "id"=>"2", "owner "=>"blue moon farms "},
# {"name"=>"bess", "id"=>"4", "owner "=>"wolcott farms"}]}
说明
步骤如下
b = File.read(FName).split(/\n{2,}/)
#=> ["::pigs:: \nname, id, owner\npeggy, 1, wolcott farms \nsue, 2, blue moon farms\neddie, 3, sunrise farms",
# "::cows:: \nname, id, owner \ndee, 3, black hat farms \nsunny, 2, blue moon farms \nbess, 4, wolcott farms\n"]
接下来我们有
enum = b.each_with_object({})
#=> #<Enumerator: ["::pigs:: \nname, id, owner\npeggy, 1, wolcott farms \nsue, 2, blue moon farms\neddie, 3, sunrise farms",
# "::cows:: \nname, id, owner \ndee, 3, black hat farms \nsunny, 2, blue moon farms \nbess, 4, wolcott farms\n"]:each_with_object({})>
我们可以将 enum
转换为数组以查看它将生成并传递给其块的值:
enum.to_a
#=> [["::pigs:: \nname, id, owner\npeggy, 1, wolcott farms \nsue, 2, blue moon farms\neddie, 3, sunrise farms", {}],
# ["::cows:: \nname, id, owner \ndee, 3, black hat farms \nsunny, 2, blue moon farms \nbess, 4, wolcott farms\n", {}]] The empty arrays above will be populated as the calculations proceed.
我们现在将 enum
的第一个元素传递给块并分配块变量
s,h = enum.next
#=> ["::pigs:: \nname, id, owner\npeggy, 1, wolcott farms \nsue, 2, blue moon farms\neddie, 3, sunrise farms", {}]
s #=> "::pigs:: \nname, id, owner\npeggy, 1, wolcott farms \nsue, 2, blue moon farms\neddie, 3, sunrise farms"
h => {}
h
的值,一个空散列,将由块修改,如下所示。
现在对 s
和 h
的这些值执行块计算。
outer_key, inner_key_names, *inner_values = s.split(/\n/)
#=> ["::pigs:: ",
# "name, id, owner",
# "peggy, 1, wolcott farms ",
# "sue, 2, blue moon farms", "eddie, 3, sunrise farms"]
outer_key
#=> "::pigs:: "
inner_key_names
#=> "name, id, owner"
inner_values
#=> ["peggy, 1, wolcott farms ",
# "sue, 2, blue moon farms",
# "eddie, 3, sunrise farms"]
inner_keys = inner_key_names.split(/,\s+/)
#=> ["name", "id", "owner"]
h[outer_key[/(?<=::)[^:]+/]] =
inner_values.each_with_object([]) { |values_str, a|
a << inner_keys.zip(values_str.split(/,\s+/)).to_h }
# => [{"name"=>"peggy", "id"=>"1", "owner"=>"wolcott farms "},
# {"name"=>"sue", "id"=>"2", "owner"=>"blue moon farms"},
# {"name"=>"eddie", "id"=>"3", "owner"=>"sunrise farms"}]
h #=> {"pigs"=>[{"name"=>"peggy", "id"=>"1", "owner"=>"wolcott farms "},
# {"name"=>"sue", "id"=>"2", "owner"=>"blue moon farms"},
# {"name"=>"eddie", "id"=>"3", "owner"=>"sunrise farms"}]}
让我们更仔细地研究一下最后的计算。
outer_key[/(?<=::)[^:]+/]
#=> "pigs"
enum1 = inner_values.each_with_object([])
#=> #<Enumerator: ["peggy, 1, wolcott farms ", "sue, 2, blue moon farms",
# "eddie, 3, sunrise farms"]:each_with_object([])>
enum1.to_a
#=> [["peggy, 1, wolcott farms ", []],
# ["sue, 2, blue moon farms", []],
# ["eddie, 3, sunrise farms", []]]
将enum1
生成的第一个元素传递给块,并分配块变量。
values_str, a = enum1.next
#=> ["peggy, 1, wolcott farms ", []]
values_str
#=> "peggy, 1, wolcott farms "
a #=> []
现在执行块计算。
b = inner_keys.zip(values_str.split(/,\s+/))
#=> ["name", "id", "owner"].zip(["peggy", "1", "wolcott farms "])
#=> [["name", "peggy"], ["id", "1"], ["owner", "wolcott farms "]]
c = b.to_h
#=> {"name"=>"peggy", "id"=>"1", "owner"=>"wolcott farms "}
a << c
#=> [{"name"=>"peggy", "id"=>"1", "owner"=>"wolcott farms "}]
由enum1
生成的其余两个元素被类似地处理,导致
h #=> {"pigs"=>[{"name"=>"peggy", "id"=>"1", "owner"=>"wolcott farms "},
# {"name"=>"sue", "id"=>"2", "owner"=>"blue moon farms"},
# {"name"=>"eddie", "id"=>"3", "owner"=>"sunrise farms"}]
其余计算(对于奶牛)类似。
@猪和@牛
如果您坚持使用这些实例变量,则很容易从上面构造的哈希中生成它们。
h = {"pigs"=>[{"name"=>"peggy", "id"=>"1", "owner"=>"wolcott farms "},
{"name"=>"sue", "id"=>"2", "owner"=>"blue moon farms"},
{"name"=>"eddie", "id"=>"3", "owner"=>"sunrise farms"}],
"cows"=>[{"name"=>"dee", "id"=>"3", "owner "=>"black hat farms "},
{"name"=>"sunny", "id"=>"2", "owner "=>"blue moon farms "},
{"name"=>"bess", "id"=>"4", "owner "=>"wolcott farms"}]}
h.each { |k,v| instance_variable_set("@#{k}", v) }
我们现在有:
@pigs
#=> [{"name"=>"peggy", "id"=>"1", "owner"=>"wolcott farms "},
# {"name"=>"sue", "id"=>"2", "owner"=>"blue moon farms"},
# {"name"=>"eddie", "id"=>"3", "owner"=>"sunrise farms"}]
@cows
#=> [{"name"=>"dee", "id"=>"3", "owner "=>"black hat farms "},
# {"name"=>"sunny", "id"=>"2", "owner "=>"blue moon farms "},
# {"name"=>"bess", "id"=>"4", "owner "=>"wolcott farms"}]
解析文本,然后使用实例变量赋值
不能使用局部变量,但可以使用Object#instance_variable_get and Object#instance_variable_set进行这种元编程。例如:
str = File.read '/tmp/livestock.txt'
records = str.split /\n\n+/
records.map! { |r| r.split /\n/ }
records.map do |r|
var = ?@ << r.shift.strip.delete(?:)
fields = r.shift.strip.scan /[^,]+/
hashes = r.map { |e| e.split(?,).flat_map &:strip }.
map { |e| fields.zip e }.
map &:to_h
instance_variable_set var,
instance_variable_get(var).to_a.push(hashes).flatten!
end;
# The data is now stored correctly in the following instance variables.
@pigs
@cows
警告
请注意,如果 @pigs 或 @cows 已经存在,因为您正在 REPL 中进行测试,那么您的结果可能不是你期待。确保调用 Object#remove_instance_variable,将变量设置为 nil,或在测试之间创建 class 的新实例。
我想我已经从字符串创建了多个数组,但如果我尝试检查数组,我会收到错误消息。
File.open("livestock.txt", "r") do |file|
file.readlines.each do |x|
if x.match(/:*:/)
# puts x.inspect
# strip string
x.gsub!(/[^A-Za-z]/, '')
x.downcase!
puts x.inspect
x = Array.new(){Hash.new}
# puts x.inspect
pigs.inspect
else
# puts "no"
end
end
end
animals.rb:12:in `block (2 levels) in <main>': undefined local variable or method `pigs' for main:Object (NameError)
from animals.rb:2:in `each'
from animals.rb:2:in `block in <main>'
from animals.rb:1:in `open'
from animals.rb:1:in `<main>'
理想情况下我想创造猪=[] 然后将哈希添加到此数组,例如:
pigs = [{"name"=>"peggy", "id"=>1, "owner"=>"wolcott farms"},
{"name"=>"sue", "id"=>2, "owner"=>"blue moon farms"},
{"name"=>"eddie", "id"=>3, "owner"=>"sunrise farms"}
]
奶牛等也是如此
我的文本文件 animals.txt 是
::pigs::
name, id, owner
peggy, 1, wolcott farms
sue, 2, blue moon farms
eddie, 3, sunrise farms
::cows::
name, id, owner
dee, 3, black hat farms
sunny, 2, blue moon farms
bess, 4, wolcott farms
自 Ruby v1.8 以来,无法创建局部变量。实例变量,是(使用Object#instance_variable_set),局部变量,否
@CodeGnome 给出了一种创建具有给定名称的实例变量的方法。然而,我不认为实例变量的集合是合适的数据结构。我建议您考虑改用哈希。您可以按如下方式进行。
代码
def doit(fname)
File.read(fname).
split(/\n{2,}/). # split paragraphs
each_with_object({}) do |s,h|
outer_key, inner_key_names, *inner_values = s.split(/\n/)
inner_keys = inner_key_names.split(/,\s+/)
h[outer_key[/(?<=::)[^:]+/]] =
inner_values.each_with_object([]) { |values_str, a|
a << inner_keys.zip(values_str.split(/,\s+/)).to_h }
end
end
例子
首先让我们创建您的文件。
FName = "animals.txt"
data =<<_
::pigs::
name, id, owner
peggy, 1, wolcott farms
sue, 2, blue moon farms
eddie, 3, sunrise farms
::cows::
name, id, owner
dee, 3, black hat farms
sunny, 2, blue moon farms
bess, 4, wolcott farms
_
File.write(FName, data)
#=> 203
现在在此文件上执行该方法。
doit(FName)
#=> {"pigs"=>[{"name"=>"peggy", "id"=>"1", "owner"=>"wolcott farms "},
# {"name"=>"sue", "id"=>"2", "owner"=>"blue moon farms"},
# {"name"=>"eddie", "id"=>"3", "owner"=>"sunrise farms"}],
# "cows"=>[{"name"=>"dee", "id"=>"3", "owner "=>"black hat farms "},
# {"name"=>"sunny", "id"=>"2", "owner "=>"blue moon farms "},
# {"name"=>"bess", "id"=>"4", "owner "=>"wolcott farms"}]}
说明
步骤如下
b = File.read(FName).split(/\n{2,}/)
#=> ["::pigs:: \nname, id, owner\npeggy, 1, wolcott farms \nsue, 2, blue moon farms\neddie, 3, sunrise farms",
# "::cows:: \nname, id, owner \ndee, 3, black hat farms \nsunny, 2, blue moon farms \nbess, 4, wolcott farms\n"]
接下来我们有
enum = b.each_with_object({})
#=> #<Enumerator: ["::pigs:: \nname, id, owner\npeggy, 1, wolcott farms \nsue, 2, blue moon farms\neddie, 3, sunrise farms",
# "::cows:: \nname, id, owner \ndee, 3, black hat farms \nsunny, 2, blue moon farms \nbess, 4, wolcott farms\n"]:each_with_object({})>
我们可以将 enum
转换为数组以查看它将生成并传递给其块的值:
enum.to_a
#=> [["::pigs:: \nname, id, owner\npeggy, 1, wolcott farms \nsue, 2, blue moon farms\neddie, 3, sunrise farms", {}],
# ["::cows:: \nname, id, owner \ndee, 3, black hat farms \nsunny, 2, blue moon farms \nbess, 4, wolcott farms\n", {}]] The empty arrays above will be populated as the calculations proceed.
我们现在将 enum
的第一个元素传递给块并分配块变量
s,h = enum.next
#=> ["::pigs:: \nname, id, owner\npeggy, 1, wolcott farms \nsue, 2, blue moon farms\neddie, 3, sunrise farms", {}]
s #=> "::pigs:: \nname, id, owner\npeggy, 1, wolcott farms \nsue, 2, blue moon farms\neddie, 3, sunrise farms"
h => {}
h
的值,一个空散列,将由块修改,如下所示。
现在对 s
和 h
的这些值执行块计算。
outer_key, inner_key_names, *inner_values = s.split(/\n/)
#=> ["::pigs:: ",
# "name, id, owner",
# "peggy, 1, wolcott farms ",
# "sue, 2, blue moon farms", "eddie, 3, sunrise farms"]
outer_key
#=> "::pigs:: "
inner_key_names
#=> "name, id, owner"
inner_values
#=> ["peggy, 1, wolcott farms ",
# "sue, 2, blue moon farms",
# "eddie, 3, sunrise farms"]
inner_keys = inner_key_names.split(/,\s+/)
#=> ["name", "id", "owner"]
h[outer_key[/(?<=::)[^:]+/]] =
inner_values.each_with_object([]) { |values_str, a|
a << inner_keys.zip(values_str.split(/,\s+/)).to_h }
# => [{"name"=>"peggy", "id"=>"1", "owner"=>"wolcott farms "},
# {"name"=>"sue", "id"=>"2", "owner"=>"blue moon farms"},
# {"name"=>"eddie", "id"=>"3", "owner"=>"sunrise farms"}]
h #=> {"pigs"=>[{"name"=>"peggy", "id"=>"1", "owner"=>"wolcott farms "},
# {"name"=>"sue", "id"=>"2", "owner"=>"blue moon farms"},
# {"name"=>"eddie", "id"=>"3", "owner"=>"sunrise farms"}]}
让我们更仔细地研究一下最后的计算。
outer_key[/(?<=::)[^:]+/]
#=> "pigs"
enum1 = inner_values.each_with_object([])
#=> #<Enumerator: ["peggy, 1, wolcott farms ", "sue, 2, blue moon farms",
# "eddie, 3, sunrise farms"]:each_with_object([])>
enum1.to_a
#=> [["peggy, 1, wolcott farms ", []],
# ["sue, 2, blue moon farms", []],
# ["eddie, 3, sunrise farms", []]]
将enum1
生成的第一个元素传递给块,并分配块变量。
values_str, a = enum1.next
#=> ["peggy, 1, wolcott farms ", []]
values_str
#=> "peggy, 1, wolcott farms "
a #=> []
现在执行块计算。
b = inner_keys.zip(values_str.split(/,\s+/))
#=> ["name", "id", "owner"].zip(["peggy", "1", "wolcott farms "])
#=> [["name", "peggy"], ["id", "1"], ["owner", "wolcott farms "]]
c = b.to_h
#=> {"name"=>"peggy", "id"=>"1", "owner"=>"wolcott farms "}
a << c
#=> [{"name"=>"peggy", "id"=>"1", "owner"=>"wolcott farms "}]
由enum1
生成的其余两个元素被类似地处理,导致
h #=> {"pigs"=>[{"name"=>"peggy", "id"=>"1", "owner"=>"wolcott farms "},
# {"name"=>"sue", "id"=>"2", "owner"=>"blue moon farms"},
# {"name"=>"eddie", "id"=>"3", "owner"=>"sunrise farms"}]
其余计算(对于奶牛)类似。
@猪和@牛
如果您坚持使用这些实例变量,则很容易从上面构造的哈希中生成它们。
h = {"pigs"=>[{"name"=>"peggy", "id"=>"1", "owner"=>"wolcott farms "},
{"name"=>"sue", "id"=>"2", "owner"=>"blue moon farms"},
{"name"=>"eddie", "id"=>"3", "owner"=>"sunrise farms"}],
"cows"=>[{"name"=>"dee", "id"=>"3", "owner "=>"black hat farms "},
{"name"=>"sunny", "id"=>"2", "owner "=>"blue moon farms "},
{"name"=>"bess", "id"=>"4", "owner "=>"wolcott farms"}]}
h.each { |k,v| instance_variable_set("@#{k}", v) }
我们现在有:
@pigs
#=> [{"name"=>"peggy", "id"=>"1", "owner"=>"wolcott farms "},
# {"name"=>"sue", "id"=>"2", "owner"=>"blue moon farms"},
# {"name"=>"eddie", "id"=>"3", "owner"=>"sunrise farms"}]
@cows
#=> [{"name"=>"dee", "id"=>"3", "owner "=>"black hat farms "},
# {"name"=>"sunny", "id"=>"2", "owner "=>"blue moon farms "},
# {"name"=>"bess", "id"=>"4", "owner "=>"wolcott farms"}]
解析文本,然后使用实例变量赋值
不能使用局部变量,但可以使用Object#instance_variable_get and Object#instance_variable_set进行这种元编程。例如:
str = File.read '/tmp/livestock.txt'
records = str.split /\n\n+/
records.map! { |r| r.split /\n/ }
records.map do |r|
var = ?@ << r.shift.strip.delete(?:)
fields = r.shift.strip.scan /[^,]+/
hashes = r.map { |e| e.split(?,).flat_map &:strip }.
map { |e| fields.zip e }.
map &:to_h
instance_variable_set var,
instance_variable_get(var).to_a.push(hashes).flatten!
end;
# The data is now stored correctly in the following instance variables.
@pigs
@cows
警告
请注意,如果 @pigs 或 @cows 已经存在,因为您正在 REPL 中进行测试,那么您的结果可能不是你期待。确保调用 Object#remove_instance_variable,将变量设置为 nil,或在测试之间创建 class 的新实例。