我循环查看单词列表,并在每个单词的开头插入字母表中的每个字母,并使用以下代码:
def add_charac_front
("a".."z").each do |letter|
@array.each do |list_word|
list_word.insert(0, letter)
puts list_word
end #ends @array loop
end #ends alphabet loop
end #ends method
但.insert
正在更改@array
,以便当我通过@array
循环显示字母“b
”时,list_word
中的第一个@array
}不是“Hello
”而是“aHello
”。
我需要完全相同的行为,但是@array
对于我运行的每个字母循环都是相同的数组。我执行此代码时它正常工作:
def add_charac_front
("a".."z").each do |letter|
@array.each do |list_word|
puts "#{letter}#{list_word}"
end #ends @array loop
end #ends alphabet loop
end #ends method
但我最终想在list_word
的不同部分插入字母,而不仅仅是前面。
我想我能做到这一点的另一种方式是.split("")
list_word
,然后.insert(0, letter)
,然后是.join
。但这似乎更麻烦。
我该怎么做?
答案 0 :(得分:2)
Ruby通过引用传递,而不是通过值传递。这意味着list_word
实际上指向@array
内的原始单词。
如果您只想使用list_word
而不影响原始数组,则需要制作它的丢弃副本,例如:
def add_charac_front
("a".."z").each do |letter|
@array.each do |orig_word|
list_word = orig_word.dup # duplicates the list_word
list_word.insert(0, letter)
puts list_word
end #ends @array loop
end #ends alphabet loop
end #ends method
答案 1 :(得分:1)
您还可以使用双引号轻松创建一个新字符串,并使用#{varname}创建一个新字符串。
irb> @array = %w(foo bar baz)
=> ["foo", "bar", "baz"]
irb> ("a".."e").inject([]) { |m,c|
m.concat(@array.map { |item| "#{c}-#{item}" });
m }
=> ["a-foo", "a-bar", "a-baz", "b-foo", "b-bar", "b-baz", "c-foo", "c-bar", "c-baz", "d-foo", "d-bar", "d-baz", "e-foo", "e-bar", "e-baz"]
使用map创建新数组的错误较少,然后当您需要将另一个数组折叠到其中时,请使用inject。如果使用注射感觉不舒服,可以使用map和flatten来实现相同的结果:
irb> ("a".."e").map { |c| @array.map { |item| "#{c}-#{item}" } }
=> [["a-foo", "a-bar", "a-baz"], ["b-foo", "b-bar", "b-baz"], ["c-foo", "c-bar", "c-baz"], ["d-foo", "d-bar", "d-baz"], ["e-foo", "e-bar", "e-baz"]]
irb> ("a".."e").map { |c| @array.map { |item| "#{c}-#{item}" } }.flatten
=> ["a-foo", "a-bar", "a-baz", "b-foo", "b-bar", "b-baz", "c-foo", "c-bar", "c-baz", "d-foo", "d-bar", "d-baz", "e-foo", "e-bar", "e-baz"]
在Enumerables上使用链式操作可以轻松检查执行中每个点的状态。然后当你需要打印出来时,你可以追加.each {| x |把x}
如果你这么做了,为什么不安装gem cartesian,这使得获得两个阵列的笛卡尔积很简单,这就是你需要的:
irb> require 'cartesian'
=> true
irb> Cartesian::product(("a".."c"), %w(foo bar baz))
=> [["a", "foo"], ["a", "bar"], ["a", "baz"], ["b", "foo"], ["b", "bar"], ["b", "baz"], ["c", "foo"], ["c", "bar"], ["c", "baz"]]
irb> Cartesian::product(("a".."c"), %w(foo bar baz)).map { |x| "#{x.first}-#{x.last}" }
=> ["a-foo", "a-bar", "a-baz", "b-foo", "b-bar", "b-baz", "c-foo", "c-bar", "c-baz"]
答案 2 :(得分:0)
如果您认为需要使用insert,则可以创建该字符串的新副本。
def add_charac_front
("a".."z").each do |letter|
@array.each do |list_word|
t = String.new(list_word).insert(0,letter)
puts t
end #ends @array loop
end #ends alphabet loop
end #ends method
答案 3 :(得分:0)
不确定我是否遵循了这些要求,但我建议您自己操作数组
# example.rb
@alpha = %w{a b c d e f g h i j k l m n o p q r s t u v w x y z}
def add_charac_front(array)
return @alpha + array
end
或者上面的代码实际上是将字母插入彼此的前面,所以它相当于反转alpha数组并将其插入前面
@reverse_alpha = alpha.reverse
def add_charac_front(array)
return @reverse_alpha + array
end
希望这会有所帮助。您也可以使用这样的范围来连接子数组
a2 = %w{b c}
a3 = @alpha[0..4] + a2 + @alpha[5..13]