I have a list of numbers, and using regex that look like this (\d)(?=\d*\1)
Example list of numbers:
1234
5678
5565
5566
5567
5656
1212
Current Output using the expression:
5565
5566
5567
5656
1212
However, I want to extract list of numbers that are in 2 pairs in 4 numbers no matter what the arrangement is. For example: 1122, 1212, 2211, 2121, 1221, 2112
Example of Desired Output: (where 5565, 5567 is false)
5566
5656
1212
I am not familiar with regex, need some help.
If your numbers are always 4 digits you can do something like this
(?:(\d)(\d)\1\2)|(?:(\d)\3(\d)\4)|(?:(\d)(\d)\6\5)
So, if you have four digit numbers you can only have two different digits in each number. With \1 you can reference the first digit, with \2 the second, etc. This regex matches the three possible distributions: abab, abba and aabb.
Example: https://regex101.com/r/cP4nI5/2
Rather than Regex, if you want plain C# code, this will do
int number = 1212;
var isDoublePair = number.ToString()
.ToCharArray()
.GroupBy(c => c)
.Select(grp => grp.Count())
.All(count => count == 2);
As commented by w.b, this can be shortened to
var isDoublePair = number.ToString()
.GroupBy(c => c)
.All(g => g.Count() == 2);
Related
I have various strings like '10001110110', '10000', '100001', '00011','0001', '111000' etc..
I need to find out the longest possible combination of 1s with no or 1 zero in between.
I have got a regex like this - (?=(1+01+))
But its not returning a group where there is no leading or trailing one.
I want to regex to consider this case too.
Currently its returning all groups
Eg. if the input string is '10110111' it returns 3 groups
{null, 1011}, {null, 110111} and {null, 10111}
I want my regex to return only 1 match with the longest combination. Is it possible to do so?
For the following rule:
I need to find out the longest possible combination of 1s with no or 1
zero in between.
you can capture 1+ times a 1, and then optionally match 0 followed by again 1+ times a 1 in the lookahead assertion.
(?=(1+(?:0?1+)?))
Regex demo | C# demo
To get the longest result, you can process the matches, and then sort by the length of the string, and then get the first result from the collection.
string pattern = #"(?=(1+(?:0?1+)?))";
string input = #"10001110110 10000 100001 00011 0001 111000 101110111011011";
var result = Regex.Matches(input, pattern)
.Select(m => m.Groups[1].Value)
.OrderByDescending(s => s.Length)
.FirstOrDefault();
Console.WriteLine(result);
Output
1110111
I like to sort a list with middle 2 character. for example: The list contains following:
body1text
body2text
body11text
body3text
body12text
body13text
if I apply list.OrderBy(r => r.body), it will sort as follows:
body1text
body11text
body12text
body13text
body2text
body3text
But I need the following result:
body1text
body2text
body3text
body11text
body12text
body13text
is there any easy way to sort with middle 2 digit character?
Regards
Shuvra
The issue here is that your numbers are compared as strings, so string.Compare("11", "2") will return -1 meaning that "11" is less than "2". Assuming that your string is always in format "body" + n numbers + "text" you can match numbers with regex and parse an integer from result:
new[]
{
"body1text"
,"body2text"
,"body3text"
,"body11text"
,"body12text"
,"body13text"
}
.OrderBy(s => int.Parse(Regex.Match(s,#"\d+").Value))
I have a string which consists of numbers and letters like the example below:
string strFood = "123d 4hello12";
What I want to accomplish is get all the group of numbers which is 123, 4, and 12.
I am trying to do this via LinQ but I am not getting the array results since my plan is to get the array then add them altogether which is 123 + 4 + 12 and the result is 139.
This is what I tried so far but this doesn't result to group of string or integer:
string[] strArr =
strFood .GroupBy(y => Char.IsDigit(y)).Select(y => y.ToString()).ToArray();
I also tried this one but this returns all the number in one string:
var foo = from a in strFood .ToCharArray() where Char.IsDigit(a) == true select a;
Any help would be appreciated.
I suggest using regular expressions to find all groups (matches) with aggregation via Linq:
string strFood = "123d 4hello12";
var sum = Regex
.Matches(strFood, "[0-9]+") // groups of integer numbers
.OfType<Match>()
.Select(match => int.Parse(match.Value)) // treat each group as integer
.Sum(); // sum up
If you want to obtain an array (and sum up later):
int[] result = Regex
.Matches(strFood, "[0-9]+") // groups of integer numbers
.OfType<Match>()
.Select(match => int.Parse(match.Value))
.ToArray();
...
var sum = result.Sum();
You could split your string to integers collection:
string strFood = "123d 4hello12";
var integers = new Regex(#"\D").Split(strFood)
.Where(x=>!string.IsNullOrWhiteSpace(x))
.Select(x=>int.Parse(x));
and after that sum it with:
var sum = integers.Sum(); // Result : 139
Edit after comment of #Dmitry Bychenko: with some characters, such as persian digits that won't work.
Solution: either use
new Regex(#"[^0-9+]")
or
new Regex(#"\D", RegexOptions.ECMAScript)
Just to add decimal numbers in summation, you can use this regex instead:
var str = "123d 4hello12and0.2plus.1and-1and2+8.but 1....1 a.b";
// ^^^ ^ ^^ ^^^ ^^ ^^ ^ ^ ^ ^^
var s = Regex
.Matches(str, #"-?([0-9]+|[0-9]*\.[0-9]+)")
.OfType<Match>()
.Sum(c=> double.Parse(c.Value, CultureInfo.InvariantCulture));
Result will be:
Count = 11
[0]: {123}
[1]: {4}
[2]: {12}
[3]: {0}
[4]: {.2}
[5]: {.1}
[6]: {-1}
[7]: {2}
[8]: {8}
[9]: {1}
[10]: {.1}
Sum = 149.39999999999998 //~= 149.4
var yourSum = strFood.Where(x=>Char.IsDigit(x)).Select(x=>Convert.ToInt32(x)).Sum()
This will give you the sum of all numbers in your string.
If you want just an IEnumerable of ints remove the Sum() from the end
Why don't you use a simple regular expression?
string input = "123d 4hello12";
int sum = System.Text.RegularExpressions.Regex.Matches(input, #"\d+").Cast<System.Text.RegularExpressions.Match>().Sum(m => Convert.ToInt32(m.Value));
I tried using an approach using Split and Join.
First i use Linq Select to replace non digits with a ',':
strFood.Select(ch => (Char.IsDigit(ch)) ? ch : ',');
I then use Join to turn this back into a string of the form "123,,4,,,,,12", I then Split this on "," and filter out values (using Where) which have an empty string, I then convert the string into a number e.g. "123" becomes 123 and I sum the array.
Putting this all together becomes:
var Sum = String.Join("",(strFood.Select(c => (Char.IsDigit(c)) ? c : ',')))
.Split(',').Where(c => c != "").Select(c => int.Parse(c)).Sum();
Here's a slightly shorter version using Concat:
var Sum = String.Concat(strFood.Select(ch => (Char.IsDigit(ch)) ? ch : ','))
.Split(',').Where(c => c != "").Select(c => int.Parse(c)).Sum();
This gives a result of 139
Try this:
int[] strArr = strFood.ToCharArray().Where(x=> Char.IsDigit(x)).Select(y => Convert.ToInt32(y.ToString())).ToArray();
I'm trying to check if a text contains two or more specific words. The words can be in any order an can show up in the text multiple times but at least once.
If the text is a match I will need to get the information about location of the words.
Lets say we have the text :
"Once I went to a store and bought a coke for a dollar and I got another coke for free"
In this example I want to match the words coke and dollar.
So the result should be:
coke : index 37, lenght 4
dollar : index 48, length 6
coke : index 84, length 4
What I have already is this: (which I think is little bit wrong because it should contain each word at least once so the + should be there instead of the *)
(?:(\bcoke\b))\*(?:(\bdollar\b))\*
But with that regex the RegEx Buddy highlights all the three words if I ask it to hightlight group 1 and group 2.
But when I run this in C# I won't get any results.
Can you point me to the right direction ?
I don't think it's possible what you want only using regular expressions.
Here is a possible solution using regular expressions and linq:
var words = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "coke", "dollar" };
var regex = new Regex(#"\b(?:"+string.Join("|", words)+#")\b", RegexOptions.IgnoreCase);
var text = #"Once I went to a store and bought a coke
for a dollar and I got another coke for free";
var grouped = regex.Matches(text)
.OfType<Match>()
.GroupBy(m => m.Value, StringComparer.OrdinalIgnoreCase)
.ToArray();
if (grouped.Length != words.Count)
{
//not all words were found
}
else
{
foreach (var g in grouped)
{
Console.WriteLine("Found: " + g.Key);
foreach (var match in g)
Console.WriteLine(" At {0} length {1}", match.Index, match.Length);
}
}
Output:
Found: coke
At 36 length 4
At 72 length 4
Found: dollar
At 47 length 6
How about this, it is pret-tay bad but I think it has a shot at working and it is pure RegEx no extra tools.
(?:^|\W)[cC][oO][kK][eE](?:$|\W)|(?:^|\W)[dD][oO][lL][lL][aA][rR](?:$|\W)
Get rid of the \w's if you want it to capture cokeDollar or dollarCoKe etc.
during my coding I've come across a problem that involved parsing a string like this:
{15} there are 194 red balloons, {26} there are 23 stickers, {40} there are 12 jacks, ....
my code involved pulling both the sentence and the number into two separate arrays.
I've solved the problem involving parsing out the sentence into its own array using a *.Remove(0, 5) to eliminate the first part the problem with that part was that I had to make sure that the file always was written to a standard where {##} where involved however it was not as elegant as I would like in that some times the number would be {3} and i would be forced to make it { 3}.
as there were also the chance of the string containing other numbers I wasn't able to simply parse out the integers first.
int?[] array = y.Split(',')
.Select(z =>
{
int value;
return int.TryParse(z, out value) ? value : (int?)null;
})
.ToArray();
so anyway back to the problem at hand, I need to be able to parse out "{##}" into an array with each having its own element.
Here's one way to do it using positive lookaheads/lookbehinds:
string s = "{15} there are 194 red balloons, {26} there are 23 stickers, {40} there are 12 jacks";
// Match all digits preceded by "{" and followed by "}"
int[] matches = Regex.Matches(s, #"(?<={)\d+(?=})")
.Cast<Match>()
.Select(m => int.Parse(m.Value))
.ToArray();
// Yields [15, 26, 40]