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?

van
la source
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);
Sasha Reminnyi
la source
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.

Tim Pietzcker
la source
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());
Dave
la source
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!");
}
Pranay Rana
la source
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
ejcortes
la source
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

Tabares
la source
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));
spajce
la source
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);

la source
12

Vous pouvez également essayer ceci

string.Join(null,System.Text.RegularExpressions.Regex.Split(expr, "[^\\d]"));
BvdVen
la source
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);
}
Daniel Gehriger
la source
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
fubo
la source
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 ...

Richard Fu
la source
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
la source
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.

Shyam sundar shah
la source
7
var match=Regex.Match(@"a99b",@"\d+");
if(match.Success)
{
    int val;
    if(int.TryParse(match.Value,out val))
    {
        //val is set
    }
}
dépensier
la source
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.

Atters
la source
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».

À M
la source
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]
Thomas CG de Vilhena
la source
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

Tarek El-Mallah
la source
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();
            }
Manoj Gupta
la source
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);
Simba
la source
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;
    }
HS_Kernel
la source
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();

la source
0

Vous devrez utiliser Regex comme \d+

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

Sachin Shanbhag
la source
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 débutant
la source
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
la source
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
user2320464
la source
-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;
}
MrJTNY
la source