我有一个数组["Ac,Ab,Aa", "Ba,Bb,Bd", "Ca,Cc,Cb", "aA,aC,aD", "bD,bA,bB", "cB,cA,cC"]
。
如果第一个字符在循环中为大写,我想删除前三个字符,以便我可以使用每个输出。
第一次循环后我想要的输出是
["Ab,Aa", "Bb,Bd", "Cc,Cb", "aA,aC,aD", "bD,bA,bB", "cB,cA,cC"]
我正在尝试以下但我是堆栈。
arr1 = ["Ac,Ab,Aa", "Ba,Bb,Bd", "Ca,Cc,Cb", "aA,aC,aD", "bD,bA,bB", "cB,cA,cC"]
def eliminatecolumn(arr)
arr.map do |item|
if item[0]=~/[A-Z]/
item[0..2]=''
end
end
end
eliminatecolumn(arr1)
我得到["", "", "", nil, nil, nil]
。
我是Ruby新手,我很欣赏任何输入。提前谢谢。
答案 0 :(得分:4)
<强>代码强>
a.map { |str| str.sub(/..,/) { |s| (s == s.capitalize) ? "" : s } }
#=> ["Ab,Aa", "Bb,Bd", "Cc,Cb", "aA,aC,aD", "bD,bA,bB", "cB,cA,cC"]
<强>解释强>
当给String#sub一个块时,匹配将传递给块,块确定替换。 (如果没有匹配,则传递nil
。)例如,
str = "Ac,Ab,Aa"
比赛是
s = "Ac,Ab,Aa"[/..,/] #=> "Ac,"
所以
(s == s.capitalize) ? "" : s
变为
("Ac," == "Ac,") ? "" : "Ac,"
导致"Ac,"
替换为空字符串。通过对比,如果
str => "aA,aC,aD"
比赛是
s = "aA,aC,aD"[/..,/] #=> "aA,"
所以
(s == s.capitalize) ? "" : s }
变为
("aA" == "AA") ? "" : "aA" }
导致"aA"
分配其当前值(即保持不变)。
最初我有str.gsub(/^..,/)
,锚^
需要将替换限制为前三个字符,但由于每个字符串只有一个(可能的)替换,sub
可以使用,消除了锚的需要。
<强>替代强>
此解决方案的变体如下:
a.map { |str| str.sub(/[A-Z].,/) { |s| s ? "" : s } }
由于块变量是nil
或以大写字母开头的字符串,因此无需在块内确定字符串是否大写。
答案 1 :(得分:3)
你可以试试这个
a = ["Ac,Ab,Aa", "Ba,Bb,Bd", "Ca,Cc,Cb", "aA,aC,aD", "bD,bA,bB", "cB,cA,cC"]
a.collect { |str| str.first.match(/\A[A-Z]\z/) ? (str.slice!(0..2); str) : str }
=> ["Ab,Aa", "Bb,Bd", "Cc,Cb", "aA,aC,aD", "bD,bA,bB", "cB,cA,cC"]
答案 2 :(得分:2)
您可以使用:
arr.map do |item|
item = item.gsub(/^[A-Z]../, '')
end
答案 3 :(得分:1)
喜欢这个吗?
arr = ["Ac,Ab,Aa", "Ba,Bb,Bd", "Ca,Cc,Cb", "aA,aC,aD", "bD,bA,bB", "cB,cA,cC"]
arr.each{ |x|
if x[0] =~ /[A-Z]/
x = x[3..-1]
puts x
end
}
答案 4 :(得分:1)
我想建议: -
arr = ["Ac,Ab,Aa", "Ba,Bb,Bd", "Ca,Cc,Cb", "aA,aC,aD", "bD,bA,bB", "cB,cA,cC"]
arr.each_with_object([]){|e, o| o << e unless e[0][/[A-Z]/]}
#=> ["aA,aC,aD", "bD,bA,bB", "cB,cA,cC"]
如果你想纠正你的方法,你可以使用以下任何一种方法: -
1)
def eliminatecolumn(arr)
arr.map do |item|
if item[0]=~/[A-Z]/
item[0..7]= ''
end
end
arr.delete("")
arr
end
2。)
def eliminatecolumn(arr)
arr.map.with_index do |item, i|
if item[0][/[A-Z]/]
arr[i] = nil
end
end
arr.compact
end
答案 5 :(得分:1)
很好的红宝石方法是:
arr = ["Ac,Ab,Aa", "Ba,Bb,Bd", "Ca,Cc,Cb", "aA,aC,aD", "bD,bA,bB", "cB,cA,cC"]
arr.map! do |string|
string.slice!(0,3) if string =~ /^[[:upper:]]/
string
end.delete_if(&:empty?)
我正在使用regexp来检查第一个字符是否为大写。块需要在修剪后返回字符串,因为String#slice!
方法返回已删除的字符串部分。 Array#map!
方法对正在迭代的数组进行更改,而不是构建新数组。最后需要Array#delete_if
来删除没有内容的字符串(即,在调用true
方法时返回empty?
值。)
答案 6 :(得分:1)
虽然你的想法非常好,但你的代码中有两个错误。
表达式item[0..2] = ''
的计算结果为''
,因此对于/[A-Z]/
中第一个字符与arr
匹配的每个字符串,结果数组中都会得到一个空字符串
传递给map
的块内的条件表达式缺少else
子句,因此对于与che条件不匹配的每个字符串,您得到一个nil
结果数组。
代码的更正版本为:
def eliminate_column(ary)
ary.map do |item|
item[0..2] = '' if item[0] =~ /[A-Z]/
item
end
end
根据替代方案,我会选择:
def eliminate_column(ary)
ary.map { |s| s.sub(/\A[A-Z]../, '') }
end
eliminate_columns(arr1)
# => ["Ab,Aa", "Bb,Bd", "Cc,Cb", "aA,aC,aD", "bD,bA,bB", "cB,cA,cC"]
与您的解决方案略有不同,因为它会使ary
内的字符串保持完整,而您使用表达式item[0..2] = ''
修改它们。要重现代码的确切行为,只需使用sub
重新sub!
。
答案 7 :(得分:0)
看起来你已经拥有它,如果你想知道如何循环输入这里是我会这样做的方式。 (虽然我认为我倾向于偏爱懒惰的普查员。
arr = ["Ac,Ab,Aa", "Ba,Bb,Bd", "Ca,Cc,Cb", "aA,aC,aD", "bD,bA,bB", "cB,cA,cC"]
arr.each do
|item|
item.split(/,/).lazy.take_while {|x| x[0] =~ /[a-z]/}.map {|x| # Do your stuff here}.force
end
这不会返回剩余物品的地图,但你还没有说你是否喜欢它们?