如果第一个字符是Ruby中的大写字母,如何删除前3个字符

时间:2014-04-08 11:58:11

标签: ruby regex gsub

我有一个数组["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新手,我很欣赏任何输入。提前谢谢。

8 个答案:

答案 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)

虽然你的想法非常好,但你的代码中有两个错误。

  1. 表达式item[0..2] = ''的计算结果为'',因此对于/[A-Z]/中第一个字符与arr匹配的每个字符串,结果数组中都会得到一个空字符串

  2. 传递给map的块内的条件表达式缺少else子句,因此对于与che条件不匹配的每个字符串,您得到一个nil结果数组。

  3. 代码的更正版本为:

    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

这不会返回剩余物品的地图,但你还没有说你是否喜欢它们?