How to extract multiple numbers from the string? - c#

I want to to extract multiple numbers from a string. The string may be like below:
hello:123.11,good:456,bye:789.78
And I want to get 3 numbers(including both integer and float numbers): 123.11, 456, 789.78 by C#.
Updated: including float number, not all integer.
How?
Thanks!

Try using Matches method of the Regex class with regex to get all the occurrence of the digits.
using System;
using System.Text.RegularExpressions;
public class Program
{
public static void Main()
{
var subjectString = "hello:123,good:456,bye:789";
var result = Regex.Matches(subjectString, #"[-+]?(\d*[.])?\d+");
foreach(var item in result)
{
Console.WriteLine(item);
}
}
}
DOT NET FIDDLE

using System.IO;
using System;
using System.Collections.Generic;
class Program
{
static void Main()
{
string digitsOnly = String.Empty;
string s = "2323jh213j21h3j2k19hk";
List<int> MyNumbers = new List<int>();
foreach (char c in s)
{
if (c >= '0' && c <= '9') digitsOnly += c;
else
{
int NumberToSave;
bool IsIntValue = Int32.TryParse(digitsOnly, out NumberToSave);
if (IsIntValue)
{
MyNumbers.Add(Convert.ToInt16(digitsOnly));
}
digitsOnly=String.Empty;
}
}
foreach (int element in MyNumbers)
{
Console.WriteLine(element);
}
}
}

Related

Formating a string (mask?)

I found that with long.Parse, ToString can take argument and I can format it to desired string, for example.
Input:
Console.WriteLine(long.Parse("123").ToString("#-#-#"));
Output:
1-2-3
I wanted to do something similar with string, lets say I wanna parse string to format ####-###-####. Is there any way to do it without regex with one liner like example above?
EDIT
Ok, so I may be misunderstood, I didn't want to parse numbers, but string instead. I can do in python like:
'{}-{}-{}'.format(*'abc') and I will receive a-b-c. In C# it seems to work only with numbers.
Try this
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Globalization;
using System.Text;
namespace Rextester
{
public class Program
{
public static void Main(string[] args)
{
Console.WriteLine("Hello, world!");
Console.WriteLine("helloWorld".ToPhoneNumber("###-###-####"));
}
}
public static class AdvancedFormatString
{
public static string ToPhoneNumber(this string strArg, string outputformat)
{
if (outputformat == null)
return strArg;
var sb = new StringBuilder();
var i = 0;
foreach (var c in outputformat)
{
if (c == '#')
{
if (i < strArg.Length)
{
sb.Append(strArg[i]);
}
i++;
}
else
{
sb.Append(c);
}
}
return sb.ToString();
}
}
}

Converting dot notation strings to multidimensional arrays

Does anyone know of a C# equivalent of this occassional PHP task:
Convert dot syntax like "this.that.other" to multi-dimensional array in PHP
That is, to convert a list of strings like level1.level2.level3 = item into a dictionary or multidimensional array?
I'd assume the dictionary would need to hold items of type object and I'd later cast them to Dictionary<string, string> or a string if it's a final item.
Does code like this work?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
string input = "level1.level2.level3 = item";
string pattern = "^(?'keys'[^=]+)=(?'value'.*)";
Match match = Regex.Match(input, pattern);
string value = match.Groups["value"].Value.Trim();
string[] keys = match.Groups["keys"].Value.Trim().Split(new char[] {'.'}, StringSplitOptions.RemoveEmptyEntries);
Dictionary<string, List<string>> dict = new Dictionary<string, List<string>>();
foreach (string key in keys)
{
if (dict.ContainsKey("key"))
{
dict[key].Add(value);
}
else
{
dict.Add(key, new List<string>() { value });
}
}
}
}
}
I guess you could do it like this, though (i'm sure more optimization could be done)
using System;
using System.Collections.Generic;
public class Program
{
public class IndexedTree {
private readonly IDictionary<string, IndexedTree> _me;
private object _value;
private readonly string _splitKey = ".";
public IndexedTree this[string key] {
get {
return _me[key];
}
}
public object Value { get; set; }
public void Add(string dottedItem) {
if ( string.IsNullOrWhiteSpace( dottedItem ) ) {
throw new ArgumentException("dottedItem cannot be empty");
}
int index;
if ( (index = dottedItem.IndexOf( _splitKey ) ) < 0 ) {
throw new ArgumentException("dottedItem didn't contain " + _splitKey);
}
string key = dottedItem.Substring(0, index), rest = dottedItem.Substring(index + 1);
IndexedTree child;
if (_me.ContainsKey(key)) {
child = _me[key];
} else {
child = new IndexedTree( _splitKey );
_me.Add(key, child);
}
if (rest.IndexOf(_splitKey) >= 0) {
child.Add(rest);
} else {
// maybe it can be checked if there is already a value set here or not
// in case there is a warning or error might be more appropriate
child.Value = rest;
}
}
public IndexedTree(string splitKey) {
_splitKey = splitKey;
_me = new Dictionary<string, IndexedTree>();
}
}
public static void Main()
{
IndexedTree tree = new IndexedTree(".");
tree.Add("Level1.Level2.Level3.Item");
tree.Add("Level1.Level2.Value");
Console.WriteLine(tree["Level1"]["Level2"].Value);
Console.WriteLine(tree["Level1"]["Level2"]["Level3"].Value);
}
}
You could see the result here:
https://dotnetfiddle.net/EGagoz

How to extract the url+parameters out of a bbcode url tag?

The following code outputs:
http://www.google.com
http://www.google.com&lang
What is the simplest way to change the code so it outputs:
http://www.google.com
http://www.google.com&lang=en&param2=this&param3=that
CODE:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace TestRegex9928228
{
class Program
{
static void Main(string[] args)
{
string text1 = "try out [url=http://www.google.com]this site (http://www.google.com)[/url]";
Console.WriteLine(text1.ExtractParameterFromBbcodeUrlElement());
string text2 = "try out [url=http://www.google.com&lang=en&param1=this&param2=that]this site (http://www.google.com)[/url]";
Console.WriteLine(text2.ExtractParameterFromBbcodeUrlElement());
Console.ReadLine();
}
}
public static class StringHelpers
{
public static string ExtractParameterFromBbcodeUrlElement(this string line)
{
if (line == null)
return "";
else
{
if (line.Contains("]"))
{
List<string> parts = line.BreakIntoParts(']');
if (parts[0].Contains("="))
{
List<string> sides = parts[0].BreakIntoParts('=');
if (sides.Count > 1)
return sides[1];
else
return "";
}
else
return "";
}
else
return "";
}
}
public static List<string> BreakIntoParts(this string line, char separator)
{
if (String.IsNullOrEmpty(line))
return new List<string>();
else
return line.Split(separator).Select(p => p.Trim()).ToList();
}
}
}
Simplest or most efficient? You're asking two different questions it seems. Simplest would be something like this:
Change:
List<string> sides = parts[0].BreakIntoParts('=');
if (sides.Count > 1)
return sides[1];
To:
List<string> sides = parts[0].BreakIntoParts('=');
if (sides.Count > 1)
return parts[0].Replace(sides[0], "");
Edit: Looks like you changed title to remove "most efficient". Here's the simplest change (fewest lines of code changed) that I see.

What Regex can strip e.g. "note:" and "firstName: " from the left of a string?

I need to strip the "label" off the front of strings, e.g.
note: this is a note
needs to return:
note
and
this is a note
I've produced the following code example but am having trouble with the regexes.
What code do I need in the two ???????? areas below so that I get the desired results shown in the comments?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
namespace TestRegex8822
{
class Program
{
static void Main(string[] args)
{
List<string> lines = new List<string>();
lines.Add("note: this is a note");
lines.Add("test: just a test");
lines.Add("test:\t\t\tjust a test");
lines.Add("firstName: Jim"); //"firstName" IS a label because it does NOT contain a space
lines.Add("She said this to him: follow me."); //this is NOT a label since there is a space before the colon
lines.Add("description: this is the first description");
lines.Add("description:this is the second description"); //no space after colon
lines.Add("this is a line with no label");
foreach (var line in lines)
{
Console.WriteLine(StringHelpers.GetLabelFromLine(line));
Console.WriteLine(StringHelpers.StripLabelFromLine(line));
Console.WriteLine("--");
//note
//this is a note
//--
//test
//just a test
//--
//test
//just a test
//--
//firstName
//Jim
//--
//
//She said this to him: follow me.
//--
//description
//this is the first description
//--
//description
//this is the first description
//--
//
//this is a line with no label
//--
}
Console.ReadLine();
}
}
public static class StringHelpers
{
public static string GetLabelFromLine(this string line)
{
string label = line.GetMatch(#"^?:(\s)"); //???????????????
if (!label.IsNullOrEmpty())
return label;
else
return "";
}
public static string StripLabelFromLine(this string line)
{
return ...//???????????????
}
public static bool IsNullOrEmpty(this string line)
{
return String.IsNullOrEmpty(line);
}
}
public static class RegexHelpers
{
public static string GetMatch(this string text, string regex)
{
Match match = Regex.Match(text, regex);
if (match.Success)
{
string theMatch = match.Groups[0].Value;
return theMatch;
}
else
{
return null;
}
}
}
}
Added
#Keltex, I incorporated your idea as follows but it is not matching any of the text (all entries are blank), what do I need to tweak in the regex?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
namespace TestRegex8822
{
class Program
{
static void Main(string[] args)
{
List<string> lines = new List<string>();
lines.Add("note: this is a note");
lines.Add("test: just a test");
lines.Add("test:\t\t\tjust a test");
lines.Add("firstName: Jim"); //"firstName" IS a label because it does NOT contain a space
lines.Add("first name: Jim"); //"first name" is not a label because it contains a space
lines.Add("description: this is the first description");
lines.Add("description:this is the second description"); //no space after colon
lines.Add("this is a line with no label");
foreach (var line in lines)
{
LabelLinePair llp = line.GetLabelLinePair();
Console.WriteLine(llp.Label);
Console.WriteLine(llp.Line);
Console.WriteLine("--");
}
Console.ReadLine();
}
}
public static class StringHelpers
{
public static LabelLinePair GetLabelLinePair(this string line)
{
Regex regex = new Regex(#"(?<label>.+):\s*(?<text>.+)");
Match match = regex.Match(line);
LabelLinePair labelLinePair = new LabelLinePair();
labelLinePair.Label = match.Groups["label"].ToString();
labelLinePair.Line = match.Groups["line"].ToString();
return labelLinePair;
}
}
public class LabelLinePair
{
public string Label { get; set; }
public string Line { get; set; }
}
}
SOLVED:
Ok, I got it to work, plus added a little hack to take care of the labels with spaces and it's exactly what I wanted, THANKS!
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
namespace TestRegex8822
{
class Program
{
static void Main(string[] args)
{
List<string> lines = new List<string>();
lines.Add("note: this is a note");
lines.Add("test: just a test");
lines.Add("test:\t\t\tjust a test");
lines.Add("firstName: Jim"); //"firstName" IS a label because it does NOT contain a space
lines.Add("first name: Jim"); //"first name" is not a label because it contains a space
lines.Add("description: this is the first description");
lines.Add("description:this is the second description"); //no space after colon
lines.Add("this is a line with no label");
lines.Add("she said to him: follow me");
foreach (var line in lines)
{
LabelLinePair llp = line.GetLabelLinePair();
Console.WriteLine(llp.Label);
Console.WriteLine(llp.Line);
Console.WriteLine("--");
}
Console.ReadLine();
}
}
public static class StringHelpers
{
public static LabelLinePair GetLabelLinePair(this string line)
{
Regex regex = new Regex(#"(?<label>.+):\s*(?<text>.+)");
Match match = regex.Match(line);
LabelLinePair llp = new LabelLinePair();
llp.Label = match.Groups["label"].ToString();
llp.Line = match.Groups["text"].ToString();
if (llp.Label.IsNullOrEmpty() || llp.Label.Contains(" "))
{
llp.Label = "";
llp.Line = line;
}
return llp;
}
public static bool IsNullOrEmpty(this string line)
{
return String.IsNullOrEmpty(line);
}
}
public class LabelLinePair
{
public string Label { get; set; }
public string Line { get; set; }
}
}
Can't you simply split the string on the first colon, or if there's no colon there's no label?
public static class StringHelpers
{
public static string GetLabelFromLine(this string line)
{
int separatorIndex = line.IndexOf(':');
if (separatorIndex > 0)
{
string possibleLabel = line.Substring(0, separatorIndex).Trim();
if(possibleLabel.IndexOf(' ') < 0)
{
return possibleLabel;
}
}
else
{
return string.Empty;
}
}
public static string StripLabelFromLine(this string line)
{
int separatorIndex = line.IndexOf(':');
if (separatorIndex > 0)
{
return line.Substring(separatorIndex + 1,
line.Length - separatorIndex - 1).Trim();
}
else
{
return line;
}
}
public static bool IsNullOrEmpty(this string line)
{
return String.IsNullOrEmpty(line);
}
}
It would probably look like this:
Regex myreg = new Regex(#"(?<label>.+):\s*(?<text>.+)");
Match mymatch = myreg.Match(text);
if(mymatch.IsMatch)
{
Console.WriteLine("label: "+mymatch.Groups["label"]);
Console.WriteLine("text: "+mymatch.Groups["text"]);
}
I used named matches above, but you could do without them. Also, I think this is a little more efficient than doing two method calls. One regex gets both the text and the label.
This regex works (see it in action on rubular):
(?: *([^:\s]+) *: *)?(.+)
This captures the label, if any, into \1, and the body into \2.
It has plenty of allowance for whitespaces, so labels can be indented, etc.

How can I display my results in C#?

I have a program see below
I made the method but I want to display it in the console
and not on the easy way like console.writeline(str.length). I want using the method I made.
could someone help me please
thanks in advance
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication3
{
class Program
{
static void Main(string[] args)
{
string str = "dit is een test 1,2,3";
Console.WriteLine(str);
}
public int CountAllNumbersAndChar(string str)
{
return str.Length;
}
}
}
Update:
I have the following program now
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication3
{
class Program
{
static void Main(string[] args)
{
string str = "this is a test 1,2,3";
int length = CountAllNumbersAndChar(str);
Console.WriteLine(str);
Console.WriteLine(length);// met de methode maar kan handiger met onderstaand voor beeld
// Console.WriteLine(str.Length);
// int numbers = str.Count(Char.IsNumber); // de makelijkste makelijke manier
//Console.WriteLine(numbers);
int countnumber = CountNumbers(str) ;
Console.WriteLine(countnumber);
int countwords = words(str);
Console.WriteLine(countwords);
}
public static int CountAllNumbersAndChar(string str)
{
return str.Length;
}
public static int CountNumbers(string str)
{
return str.Count(Char.IsNumber);
}
public static int words(string str)
{
int words = str.Split().Count(str => str.All(Char.IsLetter));
}
}
}
but it still doesnt work
could someone say me what I have to change ?
Is this what you want?
Console.WriteLine(CountAllNumbersAndChar(str));
Here's how you do it. Note public static int CountAllNumbersAndChar(string str) in the code below. You can't call CountAllNumbersAndChar from Main if you don't declare it as static.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication3
{
class Program
{
static void Main(string[] args)
{
string str = "this is a test 1,2,3";
int length = CountAllNumbersAndChar(str);
Console.WriteLine(length);
}
public static int CountAllNumbersAndChar(string str)
{
return str.Length;
}
}
}
You could use LINQ for all these tasks. Although I'm not sure you are familiar with it. It's really simple though, so have a look at the code and see if you can follow.
string str = "dit is een test 1,2,3";
// Length of the string
int chars = str.Length;
// LINQ: Count all characters that is a number
int numbers = str.Count(Char.IsNumber);
// LINQ: Split the string on whitespace and count the
// elements that contains only letters
int words = str.Split().Count(s => s.All(Char.IsLetter));
Console.WriteLine(chars); // -> 21
Console.WriteLine(numbers); // -> 3
Console.WriteLine(words); // -> 4
Of course, the way I'm counting words there is not perfect, but it should get you started. For more accurate ways you should google it as there are hundreds of examples out there.
I think you want to count number of numbers inside your string
public int CountAllNumbersAndChar(string str)
{
return str.Split(new char[]{' ',','},
StringSplitOptions.RemoveEmptyEntries).Count
(
x=>
{
int d;
return int.TryParse(x,out d);
}
);
}

Categories