Encuentra y extrae un número de una cadena

320

Tengo un requisito para encontrar y extraer un número contenido dentro de una cadena.

Por ejemplo, a partir de estas cadenas:

string test = "1 test"
string test1 = " 1 test"
string test2 = "test 99"

¿Cómo puedo hacer esto?

camioneta
fuente
2
¿Podría el número ser negativo? Si es así, ¿cómo se manejaría "Hola, ¿cómo estás? -30"?
Jon Skeet
Hola John, no hay números negativos en los datos
van
44
Números decimales como 1.5? Notación exponencial como 1.5E45?
Tim Pietzcker
Similar (pero no idéntico): stackoverflow.com/questions/1561273/…
finnw
3
¿Por qué no se acepta respuesta aquí?
Wiktor Stribiżew

Respuestas:

63

ir a través de la cuerda y usar Char.IsDigit

string a = "str123";
string b = string.Empty;
int val;

for (int i=0; i< a.Length; i++)
{
    if (Char.IsDigit(a[i]))
        b += a[i];
}

if (b.Length>0)
    val = int.Parse(b);
Sasha Reminnyi
fuente
15
@Thomas: Ese código no funciona, resulta con b == "System.Linq.Enumerable..". Correcto (e incluso más simple) seríab = String.Join("", a.Where(char.IsDigit))
BlueRaja - Danny Pflughoeft
1
Buen punto, ¡eso me enseñará a no probar el código que escribo en el comentario! También puede hacer una cadena de una matriz de caracteres utilizando el new string(char[])constructor.
Thomas
1
Regex hace un trabajo mucho mejor.
Jason Kelley
@BlueRaja - Danny Pflughoeft ¿Por qué no hacer que tu comentario sea una respuesta adecuada para que pueda votarlo
?:
NOTA: Si la cadena contiene varios números, esta respuesta los ejecutará todos juntos en un solo número. Por ejemplo, "a12bcd345" da como resultado "12345". (Lo que puede ser deseable o no, dependiendo del objetivo). Esto es diferente de la solución Regex más votada, que arrojaría "12" para el caso anterior. Esto es importante para casos como los números de teléfono "555-111-2222".
ToolmakerSteve
546

\d+es la expresión regular para un número entero. Entonces

//System.Text.RegularExpressions.Regex
resultString = Regex.Match(subjectString, @"\d+").Value;

devuelve una cadena que contiene la primera aparición de un número en subjectString.

Int32.Parse(resultString) entonces te dará el número.

Tim Pietzcker
fuente
10
para admitir números negativos que podrías usar Regex.Match(subjectString, @"-?\d+").Valueen su lugar
Jon List
45
Esta respuesta no está completa (en C #). Solo está obteniendo el primer número en la cadena. Debe iterar sobre las coincidencias: resultString = string.Join (string.Empty, Regex.Matches (subjectString, @ "\ d +"). OfType <Match> () .Select (m => m.Value));
Markus
8
@ Markus: La pregunta dice "Necesito extraer un número contenido en una cadena", y todos los ejemplos muestran un solo número presente en la cadena. Iterar sobre un solo elemento no es útil.
Tim Pietzcker
2
@ayman: Oh, ¿las comas son miles de separadores? Eso requerirá una expresión regular mucho más compleja, que debería tratarse en una pregunta separada. Un excelente punto de partida es Regular-Expressions.info, que también contiene secciones en el motor de expresiones regulares de .NET.
Tim Pietzcker
55
@DavidSopko: ¿De qué estás hablando? La pregunta original pedía una forma de extraer un solo número de una cadena, tanto en el título como en el cuerpo de la pregunta. Las ediciones posteriores a la pregunta (un año después de mi respuesta y más tarde) por personas distintas al autor original cambiaron el título a "números". En todo caso, esa edición defectuosa debería revertirse.
Tim Pietzcker
181

Así es como limpio los números de teléfono para obtener solo los dígitos:

string numericPhone = new String(phone.Where(Char.IsDigit).ToArray());
Dave
fuente
31
string numericPhone =new String(phone.Where(Char.IsDigit).ToArray());
Damith
1
solución muy elegante .. Me gusta el uso de linq
Leo Gurdian
1
¡Buena solución para enteros! Tenga en cuenta que esto no funcionará si está tratando de analizar un número decimal porque el punto decimal no es un dígito.
Elijah Lofgren
40

usar expresiones regulares ...

Regex re = new Regex(@"\d+");
Match m = re.Match("test 66");

if (m.Success)
{
    Console.WriteLine(string.Format("RegEx found " + m.Value + " at position " + m.Index.ToString()));
}
else
{
    Console.WriteLine("You didn't enter a string containing a number!");
}
Pranay Rana
fuente
33

Lo que uso para obtener números de teléfono sin puntuación ...

var phone = "(787) 763-6511";

string.Join("", phone.ToCharArray().Where(Char.IsDigit));

// result: 7877636511
ejcortes
fuente
18

Regex.Split puede extraer números de cadenas. Obtienes todos los números que se encuentran en una cadena.

string input = "There are 4 numbers in this string: 40, 30, and 10.";
// Split on one or more non-digit characters.
string[] numbers = Regex.Split(input, @"\D+");
foreach (string value in numbers)
{
    if (!string.IsNullOrEmpty(value))
    {
    int i = int.Parse(value);
    Console.WriteLine("Number: {0}", i);
    }
}

Salida:

Número: 4 Número: 40 Número: 30 Número: 10

Tabares
fuente
16

Aquí hay una Linqversión:

string s = "123iuow45ss";
var getNumbers = (from t in s
                  where char.IsDigit(t)
                  select t).ToArray();
Console.WriteLine(new string(getNumbers));
spajce
fuente
14
¿qué pasa simplemente "123iuow45ss".AsEnumerable().Where(char.IsDigit)?
Ilya Ivanov
2
Simplemente no me gusta la from t .. select tredundancia, pero de todos modos, aplausos.
Ilya Ivanov
14

Otra solución simple usando Regex Debería necesitar usar esto

using System.Text.RegularExpressions;

y el código es

string var = "Hello3453232wor705Ld";
string mystr = Regex.Replace(var, @"\d", "");
string mynumber = Regex.Replace(var, @"\D", "");
Console.WriteLine(mystr);
Console.WriteLine(mynumber);

fuente
12

también puedes probar esto

string.Join(null,System.Text.RegularExpressions.Regex.Split(expr, "[^\\d]"));
BvdVen
fuente
bueno, pero si tienes espacios entre los números en la cadena original, entonces te dará 1 cadena concatenada grande con ambos números unidos (sin espacio)
Mohammad Zekrallah
11

Simplemente use un RegEx para que coincida con la cadena, luego convierta:

Match match = Regex.Match(test , @"(\d+)");
if (match.Success) {
   return int.Parse(match.Groups[1].Value);
}
Daniel Gehriger
fuente
9

Aquí hay otro Linqenfoque que extrae el primer número de una cadena.

string input = "123 foo 456";
int result = 0;
bool success = int.TryParse(new string(input
                     .SkipWhile(x => !char.IsDigit(x))
                     .TakeWhile(x => char.IsDigit(x))
                     .ToArray()), out result);

Ejemplos:

string input = "123 foo 456"; // 123
string input = "foo 456";     // 456
string input = "123 foo";     // 123
fubo
fuente
9

Para aquellos que desean un número decimal de una cadena con Regex en DOS líneas:

decimal result = 0;
decimal.TryParse(Regex.Match(s, @"\d+").Value, out result);

Lo mismo se aplica al flotador , largo , etc.

Richard Fu
fuente
9
 string input = "Hello 20, I am 30 and he is 40";
 var numbers = Regex.Matches(input, @"\d+").OfType<Match>().Select(m => int.Parse(m.Value)).ToArray();
Ramireddy Ambati
fuente
1
Esta es la mejor respuesta que me dio lo que quería, que es una matriz de múltiples números dentro de una cadena. Si tan solo pudiera ignorar las comas en números (separador de miles), ¡eso sería perfecto! :-)
Sagar
9

Puede hacer esto usando la Stringpropiedad como a continuación:

 return new String(input.Where(Char.IsDigit).ToArray()); 

que da solo el número de la cadena.

Shyam sundar shah
fuente
7
var match=Regex.Match(@"a99b",@"\d+");
if(match.Success)
{
    int val;
    if(int.TryParse(match.Value,out val))
    {
        //val is set
    }
}
gastador
fuente
7

La pregunta no indica explícitamente que solo desea los caracteres del 0 al 9, pero no sería exagerado creer que es cierto a partir de su conjunto de ejemplos y comentarios. Así que aquí está el código que hace eso.

        string digitsOnly = String.Empty;
        foreach (char c in s)
        {
            // Do not use IsDigit as it will include more than the characters 0 through to 9
            if (c >= '0' && c <= '9') digitsOnly += c;
        }

Por qué no desea utilizar Char.IsDigit (): los números incluyen caracteres como fracciones, subíndices, superíndices, números romanos, numeradores de monedas, números encerrados y dígitos específicos de la secuencia de comandos.

Atters
fuente
6
var outputString = String.Join("", inputString.Where(Char.IsDigit));

Obtenga todos los números en la cadena. Por lo tanto, si utiliza para examaple '1 plus 2' obtendrá '12'.

Tom
fuente
5

Método de extensión para obtener todos los números positivos contenidos en una cadena:

    public static List<long> Numbers(this string str)
    {
        var nums = new List<long>();
        var start = -1;
        for (int i = 0; i < str.Length; i++)
        {
            if (start < 0 && Char.IsDigit(str[i]))
            {
                start = i;
            }
            else if (start >= 0 && !Char.IsDigit(str[i]))
            {
                nums.Add(long.Parse(str.Substring(start, i - start)));
                start = -1;
            }
        }
        if (start >= 0)
            nums.Add(long.Parse(str.Substring(start, str.Length - start)));
        return nums;
    }

Si también desea números negativos, simplemente modifique este código para manejar el signo menos ( -)

Dada esta entrada:

"I was born in 1989, 27 years ago from now (2016)"

La lista de números resultante será:

[1989, 27, 2016]
Thomas CG de Vilhena
fuente
5

si el número tiene puntos decimales, puede usar a continuación

using System;
using System.Text.RegularExpressions;

namespace Rextester
{
    public class Program
    {
        public static void Main(string[] args)
        {
            //Your code goes here
            Console.WriteLine(Regex.Match("anything 876.8 anything", @"\d+\.*\d*").Value);
            Console.WriteLine(Regex.Match("anything 876 anything", @"\d+\.*\d*").Value);
            Console.WriteLine(Regex.Match("$876435", @"\d+\.*\d*").Value);
            Console.WriteLine(Regex.Match("$876.435", @"\d+\.*\d*").Value);
        }
    }
}

resultados:

"anything 876.8 anything" ==> 876.8

"anything 876 anything" ==> 876

"$ 876435" ==> 876435

"$ 876.435" ==> 876.435

Muestra: https://dotnetfiddle.net/IrtqVt

Tarek El-Mallah
fuente
1
Muchas gracias por esta respuesta. Estoy usando C # y VS2017 y estaba tratando de descubrir cómo encuentro el valor. Gracias de nuevo por tu respuesta.
Burbujas
2
  string verificationCode ="dmdsnjds5344gfgk65585";
            string code = "";
            Regex r1 = new Regex("\\d+");
          Match m1 = r1.Match(verificationCode);
           while (m1.Success)
            {
                code += m1.Value;
                m1 = m1.NextMatch();
            }
Manoj Gupta
fuente
Este código se usa para encontrar todos los valores enteros en una cadena.
Manoj Gupta
Sería mejor agregar alguna descripción directamente en la respuesta que publicarla por separado como comentario. Los comentarios no siempre son visibles de inmediato.
John Dvorak
2

Aquí se proporciona un enfoque interesante por Ahmad Mageed, utiliza expresiones regulares y StringBuilder para extraer los números enteros en el orden en que aparecen en la cadena.

Un ejemplo de uso de Regex.Split basado en la publicación de Ahmad Mageed es el siguiente:

var dateText = "MARCH-14-Tue";
string splitPattern = @"[^\d]";
string[] result = Regex.Split(dateText, splitPattern);
var finalresult = string.Join("", result.Where(e => !String.IsNullOrEmpty(e)));
int DayDateInt = 0;

int.TryParse(finalresult, out DayDateInt);
Simba
fuente
2

Aquí está mi algoritmo

    //Fast, C Language friendly
    public static int GetNumber(string Text)
    {
        int val = 0;
        for(int i = 0; i < Text.Length; i++)
        {
            char c = Text[i];
            if (c >= '0' && c <= '9')
            {
                val *= 10;
                //(ASCII code reference)
                val += c - 48;
            }
        }
        return val;
    }
HS_Kernel
fuente
1

aqui esta mi solucion

string var = "Hello345wor705Ld";
string alpha = string.Empty;
string numer = string.Empty;
foreach (char str in var)
{
    if (char.IsDigit(str))
        numer += str.ToString();
    else
        alpha += str.ToString();
}
Console.WriteLine("String is: " + alpha);
Console.WriteLine("Numeric character is: " + numer);
Console.Read();

fuente
0

Tendrás que usar Regex como \d+

\d coincide con dígitos en la cadena dada.

Sachin Shanbhag
fuente
0
static string GetdigitFromString(string str)
    {
        char[] refArray = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
        char[] inputArray = str.ToCharArray();
        string ext = string.Empty;
        foreach (char item in inputArray)
        {
            if (refArray.Contains(item))
            {
                ext += item.ToString();
            }
        }
        return ext;
    }
Ruby Beginner
fuente
0
string s = "kg g L000145.50\r\n";
        char theCharacter = '.';
        var getNumbers = (from t in s
                          where char.IsDigit(t) || t.Equals(theCharacter)
                          select t).ToArray();
        var _str = string.Empty;
        foreach (var item in getNumbers)
        {
            _str += item.ToString();
        }
        double _dou = Convert.ToDouble(_str);
        MessageBox.Show(_dou.ToString("#,##0.00"));
watcharachai unvijit
fuente
0

Usando la respuesta @ tim-pietzcker de arriba , lo siguiente funcionará PowerShell.

PS C:\> $str = '1 test'
PS C:\> [regex]::match($str,'\d+').value
1
usuario2320464
fuente
-3

Basado en la última muestra, creé un método:

private string GetNumberFromString(string sLongString, int iLimitNumbers)
{
    string sReturn = "NA";
    int iNumbersCounter = 0;
    int iCharCounter = 0; 

    string sAlphaChars = string.Empty;
    string sNumbers = string.Empty;
    foreach (char str in sLongString)
    {
        if (char.IsDigit(str))
        {
            sNumbers += str.ToString();
            iNumbersCounter++;
            if (iNumbersCounter == iLimitNumbers)
            {
                return sReturn = sNumbers;
            }
        }
        else
        {
            sAlphaChars += str.ToString();
            iCharCounter++;
            // reset the counter 
            iNumbersCounter = 0; 
        }
    }
    return sReturn;
}
MrJTNY
fuente