This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
How would you count occurences of a string within a string (C#)?
I want to check if a String contains 2 things..
String hello = "hellohelloaklsdhas";
if hello.Contains(*hello 2 Times*); -> True
How can I solve this?
You could use a regex :)
return Regex.Matches(hello, "hello").Count == 2;
This matches the string hello for the pattern "hello" and returns true if the count is 2.
Regular expressions.
if (Regex.IsMatch(hello,#"(.*hello.*){2,}"))
I guess you meant "hello", and this will match a string with at least 2 "hello" (not exactly 2 "hello")
public static class StringExtensions
{
public static int Matches(this string text, string pattern)
{
int count = 0, i = 0;
while ((i = text.IndexOf(pattern, i)) != -1)
{
i += pattern.Length;
count++;
}
return count;
}
}
class Program
{
static void Main()
{
string s1 = "Sam's first name is Sam.";
string s2 = "Dot Net Perls is about Dot Net";
string s3 = "No duplicates here";
string s4 = "aaaa";
Console.WriteLine(s1.Matches("Sam")); // 2
Console.WriteLine(s1.Matches("cool")); // 0
Console.WriteLine(s2.Matches("Dot")); // 2
Console.WriteLine(s2.Matches("Net")); // 2
Console.WriteLine(s3.Matches("here")); // 1
Console.WriteLine(s3.Matches(" ")); // 2
Console.WriteLine(s4.Matches("aa")); // 2
}
}
You can use a regex, and check the length of the result of Matches function. If it's two you win.
new Regex("hello.*hello").IsMatch(hello)
or
Regex.IsMatch(hello, "hello.*hello")
If you use a regular expression MatchCollection you can get this easily:
MatchCollection matches;
Regex reg = new Regex("hello");
matches = reg.Matches("hellohelloaklsdhas");
return (matches.Count == 2);
IndexOf
You can use the IndexOf method to get the index of a certain string. This method has an overload that accepts a starting point, from where to look. When the specified string is not found, -1 is returned.
Here is an example that should speak for itself.
var theString = "hello hello bye hello";
int index = -1;
int helloCount = 0;
while((index = theString.IndexOf("hello", index+1)) != -1)
{
helloCount++;
}
return helloCount==2;
Regex
Another way to get the count is to use Regex:
return (Regex.Matches(hello, "hello").Count == 2);
IndexOf:
int FirstIndex = str.IndexOf("hello");
int SecondIndex = str.IndexOf("hello", FirstIndex + 1);
if(FirstIndex != -1 && SecondIndex != -1)
{
//contains 2 or more hello
}
else
{
//contains not
}
or if you want exactly 2: if(FirstIndex != -1 && SecondIndex != -1 && str.IndexOf("hello", SecondIndex) == -1)
Related
So I have 2 string first is RJPDLLDHLDHAFASR and the second one is ASRAFLDHLDHDLRJP.
What could be the best way of comparing these two?
If one segregates this string into sub-strings then it can be observed how these 2 strings are similar. Sub strings RJP DL LDH LDH AF ASR.
That's true that I need a pattern where I should find above mentioned sub strings as a string in both the bigger strings.
So I gave this a try on my lunch break. I used the rotation method I mentioned in the comments. This seems to work but there's probably room for improvement.
// Rotate a string 1 character to the right
// ex: "abc" -> "cba"
static string RotateRight(string s)
{
return s[s.Length - 1] + s.Substring(0, s.Length - 1);
}
// Compare 2 strings using first n letters
static bool StrNCmp(string s1, string s2, int n)
{
if (n == 0 || n > s1.Length || n > s1.Length) return false;
return s1.Substring(0, n) == s2.Substring(0, n);
}
// Rotate s2 until a match with s1 is found.
// Return number of rotations or -1 if no match found
static int FindMatch(string s1, ref string s2)
{
var count = 0;
while (!StrNCmp(s1, s2, count))
{
s2 = RotateRight(s2);
count += 1;
// Gone all the way around - stop
if (count > s2.Length) return -1;
}
return count;
}
static void Main(string[] args)
{
var s1 = "RJPDLLDHLDHAFASR";
var s2 = "ASRAFLDHLDHDLRJP";
while (s1.Length != 0)
{
var count = FindMatch(s1, ref s2);
if (count == -1)
{
Console.WriteLine("FAIL");
break;
}
Console.WriteLine(s1.Substring(0, count));
// Remove matched chars
s1 = s1.Substring(count);
s2 = s2.Substring(count);
}
}
Output:
RJP
DL
LDH
LDH
AF
ASR
Version 2 using a stack. You can do it without a stack, just lop off the last char in s2, but a stack makes it easier.
static int FindMatch(string s1, Stack<char> stack)
{
string built = "";
do
{
char prev = stack.Pop();
built = prev + built;
if (s1.StartsWith(built))
{
return built.Length;
}
} while (stack.Count() > 0) ;
return -1;
}
static void Main(string[] args)
{
var s1 = "RJPDLLDHLDHAFASR";
var s2 = "ASRAFLDHLDHDLRJP";
Stack<char> stack = new Stack<char>();
foreach (var c in s2) stack.Push(c);
while (s1.Length != 0)
{
var count = FindMatch(s1, stack);
if (count == -1)
{
Console.WriteLine("FAIL");
break;
}
Console.WriteLine(s1.Substring(0, count));
// Remove matched chars
s1 = s1.Substring(count);
}
}
Take first letter in the first string. Iterate second string from the start, searching for this letter. When you find it try to match the substring made in the second string from that letter to the end with the substring of the same length in the first string. If they match remove the substrings and repeat the process. If you get two empty strings then the original strings are matched by this "reverse substring" criteria.
I'm working on figuring out a good regular expression that would take a value such as:
Transformer Winding Connections (Wye (Star) or Delta)
and would match:
Wye (Star) or Delta
What I have so far is:
string longName = "Transformer Winding Connections (Wye (Star) or Delta)";
// Match everything until first parentheses
Regex nameRegex = new Regex(#"([^(]*)");
Match nameMatch = nameRegex.Match(longName);
// Match everything from first parentheses on
Regex valueRegex = new Regex(#"\(.+\)");
Match valueMatch = valueRegex.Match(longName);
valueMatch is returning:
(Wye (Star) or Delta)
Is there some clever way to only remove the first set of parentheses in C#?
If you want to deal with only one level then this would be fine.
#"\((?:\([^()]*\)|[^()])*\)"
or
If you don't want to match the outer paranthesis.
#"(?<=\()(?:\([^()]*\)|[^()])*(?=\))"
DEMO
Here's the non-regex solution I mentioned in a comment, assuming your scenario is as simple as you laid out:
string longName = "Transformer Winding Connections (Wye (Star) or Delta)";
int openParenIndex = longName.IndexOf("(");
int closingParenIndex = longName.LastIndexOf(")");
if (openParenIndex == -1 || closingParenIndex == -1
|| closingParenIndex < openParenIndex)
{
// unexpected scenario...
}
string valueWithinFirstLastParens = longName.Substring(openParenIndex + 1,
closingParenIndex - openParenIndex - 1);
Try this function, which doesn't use RegEx:
private static string RemoveOuterParenthesis(string str)
{
int ndx = 0;
int firstParenthesis = str.IndexOf("(", StringComparison.Ordinal);
int balance = 1;
int lastParenthesis = 0;
while (ndx < str.Length)
{
if (ndx == firstParenthesis)
{
ndx++;
continue;
}
if (str[ndx] == '(')
balance++;
if (str[ndx] == ')')
balance--;
if (balance == 0)
{
lastParenthesis = ndx;
break;
}
ndx++;
}
return str.Remove(firstParenthesis, 1).Remove(lastParenthesis - 1, 1);
}
You'll want to clean it up a bit. Do some error checking. The functions assumes:
The string has parenthesis
The parenthesis are balanced
The string isn't null
I have strings that look like this:
1.23.4.34
12.4.67
127.3.2.21.3
1.1.1.9
This is supposed to be a collection of numbers, separated by '.' symbols, similar to an ip address. I need to increment only the last digit/digits.
Expected Output:
1.23.4.35
12.4.68
127.3.2.21.4
1.1.1.10
Basically, increment whatever the number that is after the last '.' symbol.
I tried this:
char last = numberString[numberString.Length - 1];
int number = Convert.ToInt32(last);
number = number + 1;
If I go with the above code, I just need to replace the characters after the last '.' symbol with the new number. How do I get this done, good folks? :)
It seems to me that one method would be to:
split the string on . to get an array of components.
turn the final component into an integer.
increment that integer.
turn it back into a string.
recombine the components with . characters.
See, for example, the following program:
using System;
namespace ConsoleApplication1 {
class Program {
static void Main(string[] args) {
String original = "1.23.4.34";
String[] components = original.Split('.');
int value = Int32.Parse(components[components.Length - 1]) + 1;
components[components.Length - 1] = value.ToString();
String newstring = String.Join(".",components);
Console.WriteLine(newstring);
}
}
}
which outputs the "next highest" value of:
1.23.4.35
You can use string.LastIndexOf().
string input = "127.3.2.21.4";
int lastIndex = input.LastIndexOf('.');
string lastNumber = input.Substring(lastIndex + 1);
string increment = (int.Parse(lastNumber) + 1).ToString();
string result = string.Concat(input.Substring(0, lastIndex + 1), increment);
You need to extract more than just the last character. What if the last character is a 9 and then you add 1 to it? Then you need to correctly add one to the preceding character as well. For example, the string 5.29 should be processed to become 5.30 and not simply 5.210 or 5.20.
So I suggest you split the string into its number sections. Parse the last section into an integer. Increment it and then create the string again. I leave it as an exercise for the poster to actually write the few lines of code. Good practice!
Something like this:
var ip = "1.23.4.34";
var last = int.Parse(ip.Split(".".ToCharArray(),
StringSplitOptions.RemoveEmptyEntries).Last());
last = last + 1;
ip = string.Format("{0}.{1}",ip.Remove(ip.LastIndexOf(".")) , last);
If you are dealing with IP, there will be some extra code in case of .034, which should be 035 instead of 35. But that logic is not that complicated.
It's simple as this, use Split() and Join() String methods
String test = "1.23.4.34"; // test string
String[] splits = test.Split('.'); // split by .
splits[splits.Length - 1] = (int.Parse(splits[splits.Length - 1])+1).ToString(); // Increment last integer (Note : Assume all are integers)
String answ = String.Join(".",splits); // Use string join to make the string from string array. uses . separator
Console.WriteLine(answ); // Answer : 1.23.4.35
Using a bit of Linq
int[] int_arr = numberString.Split('.').Select(num => Convert.ToInt32(num)).ToArray();
int_arr[int_arr.Length - 1]++;
numberString = "";
for(int i = 0; i < int_arr.Length; i++) {
if( i == int_arr.Length - 1) {
numberString += int_arr[i].ToString();
}
else {
numberString += (int_arr[i].ToString() + ".");
}
}
Note: on phone so can't test.
My Solution is:
private static string calcNextCode(string value, int index)
{
if (value is null) return "1";
if (value.Length == index + 1) return value + "1";
int lastNum;
int myIndex = value.Length - ++index;
char myValue = value[myIndex];
if (int.TryParse(myValue.ToString(), NumberStyles.Integer, null, out lastNum))
{
var aStringBuilder = new StringBuilder(value);
if (lastNum == 9)
{
lastNum = 0;
aStringBuilder.Remove(myIndex, 1);
aStringBuilder.Insert(myIndex, lastNum);
return calcNextCode(aStringBuilder.ToString(), index++);
}
else
{
lastNum++;
}
aStringBuilder.Remove(myIndex, 1);
aStringBuilder.Insert(myIndex, lastNum);
return aStringBuilder.ToString();
}
return calcNextCode(value, index++);
}
i have string with date , i want to split it with date and string
For example :
I have this type of strings data
9/23/2013/marking abandoned based on notes below/DB
12/8/2012/I think the thid is string/SG
and i want to make it like as
9/23/2013 marking abandoned based on notes below/DB
12/8/2013 I think the thid is string/SG
so, i don't know how to split these strings and store in different columns of table.
pls help me.
string[] vals = { "9/23/2013/marking abandoned based on notes below/DB",
"12/8/2012/I think the thid is string/SG" };
var regex = #"(\d{1,2}/\d{1,2}/\d{4})/(.*)";
var matches = vals.Select(val => Regex.Match(vals, regex));
foreach (var match in matches)
{
Console.WriteLine ("{0} {1}", match.Groups[1], match.Groups[2]);
}
prints:
9/23/2013 marking abandoned based on notes below/DB
12/8/2012 I think the thid is string/SG
(\d{1,2}/\d{1,2}/\d{4})/(.*) breaks down to
(\d{1,2}/\d{1,2}/\d{4}):
\d{1,2} - matches any one or two digit number
/ - matches to one / symbol
\d{4} - matches to four digit number
(...) - denotes first group
(.*) - matches everything else and creates second group
Another way to do it with LINQ:
var inputs = new[]{
"9/23/2013/marking abandoned based on notes below/DB",
"12/8/2012/I think the thid is string/SG"
};
foreach (var item in inputs)
{
int counter = 0;
var r = item.Split('/')
.Aggregate("", (a, b) =>
a + ((counter++ == 3) ? "\t" : ((counter == 1) ? "" : "/")) + b);
Console.WriteLine(r);
}
Or you may use the IndexOf and Substring methods:
foreach (var item in inputs)
{
var lastPos =
item.IndexOf('/',
1 + item.IndexOf('/',
1 + item.IndexOf('/')));
if (lastPos != -1)
{
var r = String.Join("\t",
item.Substring(0, lastPos),
item.Substring(lastPos + 1, item.Length - lastPos - 1));
Console.WriteLine(r);
}
}
Perhaps with pure string methods, the third slash separates the date and the text:
string line = "9/23/2013/marking abandoned based on notes below/DB";
int slashIndex = line.IndexOf('/');
if(slashIndex >= 0)
{
int slashCount = 1;
while(slashCount < 3 && slashIndex >= 0)
{
slashIndex = line.IndexOf('/', slashIndex + 1);
if(slashIndex >= 0) slashCount++;
}
if(slashCount == 3)
{
Console.WriteLine("Date:{0} Text: {1}"
, line.Substring(0, slashIndex)
, line.Substring(slashIndex +1));
}
}
For what it's worth, here is a extension method to "break" a string in half on nth occurence of astring:
public static class StringExtensions
{
public static string[] BreakOnNthIndexOf(this string input, string value, int breakOn, StringComparison comparison)
{
if (breakOn <= 0)
throw new ArgumentException("breakOn must be greater than 0", "breakOn");
if (value == null) value = " "; // fallback on white-space
int slashIndex = input.IndexOf(value, comparison);
if (slashIndex >= 0)
{
int slashCount = 1;
while (slashCount < breakOn && slashIndex >= 0)
{
slashIndex = input.IndexOf(value, slashIndex + value.Length, comparison);
if (slashIndex >= 0) slashCount++;
}
if (slashCount == breakOn)
{
return new[] {
input.Substring(0, slashIndex),
input.Substring(slashIndex + value.Length)
};
}
}
return new[]{ input };
}
}
Use it in this way:
string line1 = "9/23/2013/marking abandoned based on notes below/DB";
string line2 = "12/8/2012/I think the thid is string/SG";
string[] res1 = line1.BreakOnNthIndexOf("/", 3, StringComparison.OrdinalIgnoreCase);
string[] res2 = line2.BreakOnNthIndexOf("/", 3, StringComparison.OrdinalIgnoreCase);
I am trying to create a an function that formats US phone numbers -- hopefully without looping through each digit.
When 10 digits are passed in all is fine. How ever when more than 10 digits are passed in
I want the String.Format method to append the extension digits on the right. For example:
When 14 digits passed in the result should be:(444)555-2222 x8888
When 12 digits passed in the result should be:(444)555-2222 x88
etc.
However what I get with my current attempt is:
Passing in 12 digits returns this string '() -949 x555444433'
here is what I have so far.
public static string _FormatPhone(object phonevalue)
{
Int64 phoneDigits;
if (Int64.TryParse(phonevalue.ToString(), out phoneDigits))
{
string cleanPhoneDigits = phoneDigits.ToString();
int digitCount = cleanPhoneDigits.Length;
if (digitCount == 10)
return String.Format("{0:(###) ###-####}", phoneDigits);
else if (digitCount > 10)
return String.Format("{0:(###) ###-#### x#########}", phoneDigits);
else
return cleanPhoneDigits;
}
return "Format Err#";
}
Thanks in advance.
I think you'll have to break your phoneDigits string into the first 10 digits and the remainder.
//[snip]
else if (phoneDigits.ToString().Length > 10)
{
return String.Format("{0:(###) ###-#### x}{1}", phoneDigits.Substring(0,10), phoneDigits.Substring(10) );
}
//[snip]
I'd suggest treating it as a string of digits, not a number. You would then use Substring explicitly to break out the parts.
Trying to squeeze it into 1 line, I came up with this.
var phoneNumber = "(999) 555-4455 ext123";
phoneNumber = Regex.Replace(phoneNumber, "(.*?)([+]\\d{1,3})?(.*?)(\\d{3})(.*?)(\\d{3})(.*?)(\\d{4})([ ]+)?(x|ext)?(.*?)(\\d{2,5})?(.*?)$", "$2 $4 $6 $8 $10$12").Trim().Replace("ext","x");
If it starts with +# it will leave that alone. It will then look for blocks of numbers. 3,3,4 then it looks for ext or x for extension and another 2-5 numbers. At that point you can format it anyway you like, I chose spaces.
1234567890 -> '123 456 7890'
(123)456.7890 -> '123 456 7890'
+1 (999)555-4455 ext123 -> '+1 999 555 4455 x123'
The problem lies in your else if condition where you have a set number of # placeholders to handle the phone number extension. Instead, we can define the format dynamically to account for different lengths.
Why are you passing in an object? You're using ToString() all over the place. Why not pass in a string from the start? If the item you're passing in isn't a string then call ToString before passing it in, or save the ToString() result in a variable in the method as shown below.
Here's an updated version of your method:
public static string _FormatPhone(object phonevalue)
{
string returnPhone = "Format Err#";
Int64 phoneDigits;
string phoneNumber = phonevalue.ToString();
if (Int64.TryParse(phoneNumber, out phoneDigits))
{
if (phoneNumber.Length == 10)
{
return phoneDigits.ToString("(###) ###-####");
}
else if (phoneNumber.Length > 10)
{
// determine the length of placeholders needed for the format
string format = "(###) ###-#### x"
+ new string('#', phoneNumber.Length - 10);
return phoneDigits.ToString(format);
}
else
{
return phoneNumber;
}
}
return returnPhone;
}
To test it:
string[] inputs = { "456", "4445552222", "444555222288", "44455522226789" };
foreach (string input in inputs)
{
Console.WriteLine("Format Result: " + _FormatPhone(input));
}
There's no need for a regex in this case. If you really wanted to use one though, your replacement method needs to determine the length in order to append the extension when needed as shown below:
string[] inputs = { "456", "4445552222", "444555222288", "44455522226789" };
string pattern = #"(\d{3})(\d{3})(\d{4})(\d*)";
foreach (string input in inputs)
{
string result = Regex.Replace(input, pattern, m =>
{
if (m.Value.Length >= 10)
{
return String.Format("({0}) {1}-{2}",
m.Groups[1].Value, m.Groups[2].Value, m.Groups[3].Value)
+ (m.Value.Length > 10 ? " x" + m.Groups[4].Value : "");
}
return m.Value;
});
Console.WriteLine("Regex result: " + result);
}
using a regex:
Regex usPhoneRegex = new Regex(#"(\d{3})(\d{3})(\d{4})(.*)", RegexOptions.IgnoreCase | RegexOptions.Compiled);
string USPhoneFormatString = "$1-$2-$3 x$4";
return usPhoneRegex.Replace("312588230012999", USPhoneFormatString));
Anything after the main phone number will be returned as an extension
Since you were using an int64 in your code, my regex assumes there are no spaces or punctuation in the phone number.
-- Edit --
Ahmad pointed out that I was not handling the case of a number without an extension. So here is a revised version that uses a MatchEvaluator to do the job. Is it better than the other answers? I don't know - but it is a different approach so I thought I would toss it out there.
Regex usPhoneRegex = new Regex(#"(\d{3})(\d{3})(\d{4})(.*)", RegexOptions.IgnoreCase | RegexOptions.Compiled);
return usPhoneRegex.Replace("3125882300", new MatchEvaluator(MyClass.formatPhone))
public static string formatPhone(Match m) {
int groupIndex = 0;
string results = string.Empty;
foreach (Group g in m.Groups) {
groupIndex +=1;
switch (groupIndex) {
case 2 :
results = g.Value;
break;
case 3 :
case 4 :
results += "-" + g.Value;
break;
case 5 :
if (g.Value.Length != 0) {
results += " x " + g.Value;
}
break;
}
}
return results;
}
This should probably use a StringBuilder.
Try using regular expressions:
class Program
{
static void Main(string[] args)
{
var g = FormatUSPhone("444555222234");
}
public static string FormatUSPhone(string num)
{
string results = string.Empty;
if(num.Length == 10)
{
num = num.Replace("(", "").Replace(")", "").Replace("-", "");
const string formatPattern = #"(\d{3})(\d{3})(\d{4})";
results = Regex.Replace(num, formatPattern, "($1) $2-$3");
}else if (num.Length == 12)
{
num = num.Replace("(", "").Replace(")", "").Replace("-", "");
const string formatPattern = #"(\d{3})(\d{3})(\d{4})(\d{2})";
results = Regex.Replace(num, formatPattern, "($1) $2-$3 x$4");
}
return results;
}
I edited the above from an example I found here. Play about with the above code, see if it helps you.