Ruby의 문자열에서 숫자 추출


82

이 코드를 사용하고 있습니다.

s = line.match( /ABCD(\d{4})/ ).values_at( 1 )[0] 

다음과 같은 문자열에서 숫자를 추출하려면

ABCD1234
ABCD1235
ABCD1236

기타

작동하지만 Ruby에서 이것에 대한 다른 대안이 무엇인지 궁금합니다.

내 코드 :

ids = [] 
someBigString.lines.each {|line|
   ids << line.match( /ABCD(\d{4})/ ).values_at( 1 )[0] 
}

답변:


38
a.map {|x| x[/\d+/]}

어떻게 map이해해야 하는가 의 의미는 무엇입니까 ? 이해 collect하지만지도를 이해하는 데 항상 어려움이있었습니다.
OscarRyz

3
@Oscar 레예스는 Enumerable에서 #지도는 수집 Enumerable에서 번호 동의어입니다
웨인 콘래드

3
참고 : 숫자가 다른 문자로 분할 된 경우 숫자의 첫 "덩어리"만 가져옵니다. 따라서 '123ABC456'의 경우 '123'만 잡습니다. 모든 숫자를 얻으려면 line.gsub (/ [^ 0-9] /, '')와 같은 것을 사용하십시오.
Joshua Pinter

4
또한 이것이 제목이 요구하는 문자열이 아닌 배열과 같은 열거 형에서 작동 함을 명확히해야합니다
allenwlee

4
NoMethodError : String에 대한 정의되지 않은 메서드`map '
Garry Gomez

177

http://www.ruby-forum.com/topic/125709에 따라 많은 Ruby 방법이 있습니다 .

  1. line.scan(/\d/).join('')
  2. line.gsub(/[^0-9]/, '')
  3. line.gsub(/[^\d]/, '')
  4. line.tr("^0-9", '')
  5. line.delete("^0-9")
  6. line.split(/[^\d]/).join
  7. line.gsub(/\D/, '')

콘솔에서 각각을 시도하십시오.

해당 게시물의 벤치 마크 보고서도 확인하십시오.


24
line.delete ( "^ 0-9")는 링크에 따라 가장 빠릅니다
Weston Ganger

62

더 간단한 해결책이 있습니다

line.scan(/\d+/).first

문자열에서 연속 된 숫자의 첫 번째 일치 만 반환합니다. 그래서 'ab123cd45'.scan(/\d+/).first그냥 반환12
lacostenycoder

5

가장 간단하고 빠른 방법은 문자열에서 모든 정수를 가져 오는 것입니다.

str = 'abc123def456'

str.delete("^0-9")
=> "123456"

여기에 제공된 다른 솔루션과 긴 문자열에 대한 벤치 마크를 비교하면 이것이 훨씬 더 빠르다는 것을 알 수 있습니다.

require 'benchmark'

@string = [*'a'..'z'].concat([*1..10_000].map(&:to_s)).shuffle.join

Benchmark.bm(10) do |x|
  x.report(:each_char) do
    @string.each_char{ |c| @string.delete!(c) if c.ord<48 or c.ord>57 }
  end
  x.report(:match) do |x|
    /\d+/.match(@string).to_s
  end
  x.report(:map) do |x|
    @string.split.map {|x| x[/\d+/]}
  end
  x.report(:gsub) do |x|
    @string.gsub(/\D/, '')
  end
  x.report(:delete) do
    @string.delete("^0-9")
  end
end

             user     system      total        real
each_char    0.020000   0.020000   0.040000 (  0.037325)
match        0.000000   0.000000   0.000000 (  0.001379)
map          0.000000   0.000000   0.000000 (  0.001414)
gsub         0.000000   0.000000   0.000000 (  0.000582)
delete       0.000000   0.000000   0.000000 (  0.000060)

4
your_input = "abc1cd2"
your_input.split(//).map {|x| x[/\d+/]}.compact.join("").to_i

작동합니다.


코드가 수행하는 작업과 문제를 해결하는 이유에 대한 설명을 추가하려면 게시물을 편집하는 것이 좋습니다. 대부분 코드 만 포함하는 답변 (작동 중이더라도)은 일반적으로 OP가 문제를 이해하는 데 도움이되지 않습니다.
SuperBiasedMan

2

또 다른 해결책은 다음과 같이 작성하는 것입니다.

myString = "sami103"
myString.each_char{ |c| myString.delete!(c) if c.ord<48 or c.ord>57 } #In this case, we are deleting all characters that do not represent numbers.

이제 입력하면

myNumber = myString.to_i #or myString.to_f

이것은


일반적으로 이와 같은 서수를 사용하는 것은 멀티 바이트 문자 집합 시대의 일반적인 솔루션으로 약간 위험합니다. 다루는 문자와 문자 집합에 따라 다른 로케일에서 다른 결과를 얻을 수 있습니다.
Brendon Whateley

0

문자열에서 숫자 부분을 추출하려면 다음을 사용하십시오.

str = 'abcd1234'
/\d+/.match(str).try(:[], 0)

반환되어야합니다 1234


당신은 필요하지 않습니다 match또는 try이 문자열 일치 구문을 사용하는 경우str[/\d+/]
lacostenycoder

또한 .try이 대답은하지 않고 실패 할 수 있도록 핵심 루비는 아닙니다 active_support/core_ext/object/try.rb또는 레일
lacostenycoder
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.