Extrahieren Sie die Nummer aus der Zeichenfolge in Ruby

81

Ich benutze diesen Code:

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

So extrahieren Sie Zahlen aus Zeichenfolgen wie:

ABCD1234
ABCD1235
ABCD1236

usw.

Es funktioniert, aber ich frage mich, welche andere Alternative ich dazu in Ruby habe.

Mein Code:

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

Antworten:

38
a.map {|x| x[/\d+/]}
Glenn McDonald
quelle
Was ist die Semantik, mapwie soll ich das verstehen? Ich verstehe, collectaber ich hatte immer Probleme, die Karte zu verstehen.
OscarRyz
3
@Oscar Reyes, Enumerable # map ist ein Synonym für Enumerable # collect
Wayne Conrad
3
Zu Ihrer Information: Wenn Sie Zahlen haben, die durch andere Zeichen aufgeteilt sind, wird nur der erste "Teil" von Zahlen erfasst. Für '123ABC456' wird also nur '123' abgerufen. Verwenden Sie so etwas wie line.gsub (/ [^ 0-9] /, ''), wenn Sie alle Zahlen erhalten möchten.
Joshua Pinter
4
sollte auch klarstellen, dass dies auf einer Aufzählung wie einem Array funktioniert, nicht auf einer Zeichenfolge, wie der Titel verlangt
Allenwlee
4
NoMethodError: undefinierte Methode `map 'für String
Garry Gomez
174

Es gibt viele Ruby-Möglichkeiten gemäß http://www.ruby-forum.com/topic/125709

  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/, '')

Probieren Sie jeden auf Ihrer Konsole aus.

Überprüfen Sie auch den Benchmark-Bericht in diesem Beitrag.

Amit Patel
quelle
24
line.delete ("^ 0-9") ist die schnellste gemäß dem Link
Weston Ganger
62

Es gibt noch einfachere Lösungen

line.scan(/\d+/).first
Binärcode
quelle
Dies gibt nur die erste Übereinstimmung aufeinanderfolgender Zahlen aus der Zeichenfolge zurück. Also 'ab123cd45'.scan(/\d+/).firstwürde 12
ich
4
your_input = "abc1cd2"
your_input.split(//).map {|x| x[/\d+/]}.compact.join("").to_i

Das sollte funktionieren.

Rohit Patel
quelle
Bitte überlegen Sie, Ihren Beitrag zu bearbeiten, um weitere Erklärungen darüber zu erhalten, was Ihr Code tut und warum er das Problem löst. Eine Antwort, die meistens nur Code enthält (auch wenn sie funktioniert), hilft dem OP normalerweise nicht, ihr Problem zu verstehen.
SuperBiasedMan
4

Der einfachste und schnellste Weg besteht darin, einfach alle ganzen Zahlen aus der Zeichenfolge herauszuholen.

str = 'abc123def456'

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

Wenn wir Benchmarks auf einer langen Reihe mit einigen der anderen hier angebotenen Lösungen vergleichen, können wir sehen, dass dies um Größenordnungen schneller ist:

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)
Lacostenycoder
quelle
2

Eine andere Lösung könnte sein, zu schreiben:

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.

Nun, wenn Sie tippen

myNumber = myString.to_i #or myString.to_f

Dies sollte a zurückgeben

user2380436
quelle
Im Allgemeinen ist die Verwendung solcher Ordnungszahlen als allgemeine Lösung im Zeitalter von Mehrbyte-Zeichensätzen etwas gefährlich. Abhängig von den Zeichen, mit denen Sie sich befassen, und dem Zeichensatz können die Ergebnisse an verschiedenen Orten unterschiedlich ausfallen.
Brendon Whateley
0

Verwenden Sie Folgendes, um einen Zahlenteil aus einer Zeichenfolge zu extrahieren:

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

Es sollte zurückkehren 1234

Rajesh Paul
quelle
Sie brauchen nicht matchoder trywenn Sie diese String-Matching-Syntax verwendenstr[/\d+/]
lacostenycoder
auch .tryist nicht Kern Rubin so diese Antwort ohne versagt active_support/core_ext/object/try.rboder Schienen
lacostenycoder