Rechercher et extraire un nombre d'une chaîne


320

J'ai une obligation de trouver et d'extraire un nombre contenu dans une chaîne.

Par exemple, à partir de ces chaînes:

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

Comment puis-je faire ceci?


2
Le nombre pourrait-il être négatif? Si oui, comment serait traité "Bonjour - comment allez-vous? -30"?
Jon Skeet

Salut John, aucun nombre négatif dans les données
van

4
Des nombres décimaux comme 1.5? Notation exponentielle comme 1.5E45?
Tim Pietzcker

Similaire (mais pas identique): stackoverflow.com/questions/1561273/…
finnw

3
Pourquoi aucune réponse n'est-elle acceptée ici?
Wiktor Stribiżew

Réponses:


63

passer par la chaîne et utiliser 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);

15
@Thomas: Ce code ne fonctionne pas, il en résulte b == "System.Linq.Enumerable..". Correct (et encore plus simple) seraitb = String.Join("", a.Where(char.IsDigit))
BlueRaja - Danny Pflughoeft

1
Bon point, ça va m'apprendre à ne pas tester le code que j'écris en commentaire! Vous pouvez également créer une chaîne à partir d'un tableau de caractères à l'aide du new string(char[])constructeur.
Thomas

1
Regex fait un bien meilleur travail.
Jason Kelley

@BlueRaja - Danny Pflughoeft Pourquoi ne pas faire de votre commentaire une bonne réponse pour que je puisse voter :-)
SteveC

REMARQUE: si la chaîne contient plusieurs nombres, cette réponse les exécutera tous ensemble en un seul numéro. Par exemple, "a12bcd345" donne "12345". (Ce qui peut être souhaitable ou non, selon l'objectif.) C'est différent de la solution Regex la mieux votée, qui retournerait "12" pour le cas ci-dessus. Cela est important pour des cas comme les numéros de téléphone "555-111-2222".
ToolmakerSteve

546

\d+est l'expression rationnelle d'un nombre entier. Alors

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

renvoie une chaîne contenant la première occurrence d'un nombre dans subjectString.

Int32.Parse(resultString) vous donnera alors le numéro.


10
pour prendre en charge les nombres négatifs que vous pourriez utiliser à la Regex.Match(subjectString, @"-?\d+").Valueplace
Jon List

45
Cette réponse n'est pas complète (en C #). Il obtient uniquement le premier nombre de la chaîne. Vous devez différencier les correspondances: resultString = string.Join (string.Empty, Regex.Matches (subjectString, @ "\ d +"). OfType <Match> () .Select (m => m.Value));
Markus

8
@Markus: La question indique "J'ai besoin d'extraire un nombre contenu dans une chaîne", et tous les exemples montrent qu'un seul nombre est présent dans la chaîne. Itérer sur un seul élément n'est pas utile.
Tim Pietzcker

2
@ayman: Oh, les virgules sont des milliers de séparateurs? Cela nécessitera une expression beaucoup plus complexe - qui devrait être traitée dans une question distincte. Un excellent point de départ est Regular-Expressions.info qui contient également des sections sur le moteur d'expression régulière de .NET.
Tim Pietzcker

5
@DavidSopko: De quoi tu parles? La question d'origine demandait un moyen d'extraire un seul numéro d'une chaîne, à la fois dans le titre et dans le corps de la question. Des modifications ultérieures de la question (un an après ma réponse et plus tard) par des personnes autres que l'auteur d'origine ont changé le titre en "nombres". Si quelque chose, cette modification défectueuse doit être annulée.
Tim Pietzcker

181

Voici comment je nettoie les numéros de téléphone pour obtenir uniquement les chiffres:

string numericPhone = new String(phone.Where(Char.IsDigit).ToArray());

31
string numericPhone =new String(phone.Where(Char.IsDigit).ToArray());
Damith

1
solution très élégante .. J'aime l'utilisation de linq
Leo Gurdian

1
Belle solution pour les entiers! Sachez que cela ne fonctionnera pas si vous essayez d'analyser un nombre décimal car le point décimal n'est pas un chiffre.
Elijah Lofgren

40

utiliser une expression régulière ...

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!");
}

33

Ce que j'utilise pour obtenir des numéros de téléphone sans aucune ponctuation ...

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

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

// result: 7877636511

18

Regex.Split peut extraire des nombres des chaînes. Vous obtenez tous les nombres qui se trouvent dans une chaîne.

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);
    }
}

Production:

Nombre: 4 Nombre: 40 Nombre: 30 Nombre: 10


16

Voici une Linqversion:

string s = "123iuow45ss";
var getNumbers = (from t in s
                  where char.IsDigit(t)
                  select t).ToArray();
Console.WriteLine(new string(getNumbers));

14
qu'en est-il simplement "123iuow45ss".AsEnumerable().Where(char.IsDigit)?
Ilya Ivanov

2
Je n'aime tout simplement pas la from t .. select tredondance, mais de toute façon, applaudissements.
Ilya Ivanov

14

Une autre solution simple utilisant Regex Vous devriez avoir besoin d'utiliser ceci

using System.Text.RegularExpressions;

et le code est

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

12

Vous pouvez également essayer ceci

string.Join(null,System.Text.RegularExpressions.Regex.Split(expr, "[^\\d]"));

sympa mais si vous avez des espaces entre les nombres dans la chaîne d'origine, cela vous donnera 1 grande chaîne concaténée avec les deux nombres joints (pas d'espace)
Mohammad Zekrallah

11

Utilisez simplement un RegEx pour faire correspondre la chaîne, puis convertissez:

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

9

Voici une autre Linqapproche qui extrait le premier nombre d'une chaîne.

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);

Exemples:

string input = "123 foo 456"; // 123
string input = "foo 456";     // 456
string input = "123 foo";     // 123

9

Pour ceux qui veulent un nombre décimal à partir d'une chaîne avec Regex en DEUX lignes:

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

La même chose s'applique au flotteur , long , etc ...


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();

1
C'est la meilleure réponse qui m'a donné ce que je voulais, qui est un tableau de plusieurs nombres dans la chaîne. Si seulement il pouvait ignorer les virgules en nombre (milliers de séparateurs), ce serait parfait! :-)
Sagar

9

Vous pouvez le faire en utilisant une Stringpropriété comme ci-dessous:

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

qui ne donne que le nombre de la chaîne.


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

7

La question n'indique pas explicitement que vous voulez juste les caractères 0 à 9, mais ce ne serait pas exagéré de croire que c'est vrai à partir de votre exemple et de vos commentaires. Voici donc le code qui fait cela.

        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;
        }

Pourquoi vous ne voulez pas utiliser Char.IsDigit () - Les nombres incluent des caractères tels que des fractions, des indices, des exposants, des chiffres romains, des numérateurs de devises, des nombres encerclés et des chiffres spécifiques au script.


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

Obtenez tous les nombres dans la chaîne. Donc, si vous utilisez par exemple «1 plus 2», vous obtiendrez «12».


5

Méthode d'extension pour obtenir tous les nombres positifs contenus dans une chaîne:

    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 vous voulez également des nombres négatifs, modifiez simplement ce code pour gérer le signe moins (- )

Compte tenu de cette entrée:

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

La liste de numéros obtenue sera:

[1989, 27, 2016]

5

si le nombre a un point décimal, vous pouvez utiliser ci-dessous

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);
        }
    }
}

résultats :

"n'importe quoi 876.8 n'importe quoi" ==> 876.8

"n'importe quoi 876 n'importe quoi" ==> 876

"876435 $" ==> 876435

"876.435 $" ==> 876.435

Exemple: https://dotnetfiddle.net/IrtqVt


1
Merci beaucoup pour cette réponse. J'utilise C # et VS2017 et essayais de comprendre comment trouver la valeur. Merci encore pour votre réponse.
Bubbles


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();
            }

Ce code est utilisé pour rechercher toutes les valeurs entières dans une chaîne.
Manoj Gupta

Il serait préférable d'ajouter une description directement dans la réponse plutôt que de la poster séparément en tant que commentaire. Les commentaires ne sont pas toujours immédiatement visibles.
John Dvorak

2

Une approche intéressante est fournie ici par Ahmad Mageed, utilise Regex et stringbuilder pour extraire les entiers dans l'ordre dans lequel ils apparaissent dans la chaîne.

Un exemple utilisant Regex.Split basé sur le post d'Ahmad Mageed est le suivant:

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);

2

Voici mon algorithme

    //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;
    }

1

voici ma solution

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();

0

Vous devrez utiliser Regex comme \d+

\d correspond aux chiffres de la chaîne donnée.


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;
    }

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"));

0

En utilisant la réponse @ tim-pietzcker ci - dessus , ce qui suit fonctionnera PowerShell.

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

-3

Sur la base du dernier échantillon, j'ai créé une méthode:

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;
}
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.