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

zwghvu4y  于 2023-06-22  发布在  Ruby
关注(0)|答案(8)|浏览(80)

数组["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的新手。

ddhy6vgd

ddhy6vgd1#

编码

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或以大写字母开头的字符串,因此无需在块内确定字符串是否大写。

to94eoyn

to94eoyn2#

你可以试试这个

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"]
webghufk

webghufk3#

您可以使用以下命令:

arr.map do |item|
     item = item.gsub(/^[A-Z]../, '')
end
lmyy7pcs

lmyy7pcs4#

像这样?

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     
}
6yoyoihd

6yoyoihd5#

不错的Ruby路方法是:

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来删除没有内容的字符串(即当对它们调用empty?方法时,它们返回true值)。

06odsfpq

06odsfpq6#

我想提出这样的建议:

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
fsi0uk1n

fsi0uk1n7#

虽然你的想法很好,但你的代码中有两个错误。
1.表达式item[0..2] = ''的计算结果为'',因此,对于每个字符串,其第一个字符与arr中的/[A-Z]/匹配,您将在结果数组中获得一个空字符串。
1.传递给map的块中的条件表达式缺少一个else子句,因此对于每个不匹配条件的字符串,在结果数组中得到一个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

vsnjm48y

vsnjm48y8#

看起来你已经得到了它,如果你想知道如何循环输入,这里有一个方法,我会这样做。(尽管我认为我倾向于过于偏爱懒惰的枚举者。

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

这将不会返回一个Map的其余项目虽然但你还没有说你是否会喜欢他们或不?

相关问题