C# substring in the middle - c#

I have the following data:
D:\toto\food\Cloture_49000ert1_10_01_2013.pdf
D:\toto\food\Cloture_856589_12_01_2013.pdf
D:\toto\food\Cloture_66rr5254_10_12_2012.pdf
How can I extract the date part?
For example:
D:\toto\food\Cloture_49000ert1_10_01_2013.pdf --> 10_01_2013
D:\toto\food\Cloture_856589_12_01_2013.pdf --> 12_01_2013
D:\toto\food\Cloture_66rr5254_10_12_2012.pdf --> 10_12_2012
My idea is to use LastIndexOf(".pdf") and then count 10 character backwards.
How can I solve this using substrings or another method?

Use Substring in this case.
Retrieves a substring from this instance. The substring starts at a
specified character position.
Try like this;
string s = "D:\\toto\\food\\Cloture_490001_10_01_2013.pdf";
string newstring = s.Substring(s.Length - 14, 10);
Console.WriteLine(newstring);
Here is a DEMO.

You do not need to find index of .pdf
path.Substring(path.Length - 14, 10)

I'd do this with a Regex.
^[\w:\\]+cloture_(\d+)_([\d_]+).pdf$
Would match the date in the second group.

If the filename is always in that format, you could do something crude like this:
string filename = #"D:\toto\food\Cloture_490001_10_01_2013.pdf";
string date = filename.Substring(filename.Length - 14, 10);
That will get a substring from 10_01_2013.pdf, which is 14 characters long, but only take the first 10 characters, leaving you with 10_01_2013.
If, however, the filename is in a different format and the date could appear anywhere within the name, you may want to consider something like Regular Expressions to be able to do a match for ##_##_#### and pull that out.

try this approach:
string dateString = textString.Substring(textString.Length-14, 10);
see here as well: Extract only right most n letters from a string

If you want to use LastIndexOf then
string str = #"D:\toto\food\Cloture_490001_10_01_2013.pdf";
string temp = str.Substring(str.LastIndexOf(".pdf") - 10, 10);
And you can parse it like
DateTime dt;
if(DateTime.TryParseExact(temp, "MM_dd_yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out dt))
{
//valid
}
else
{
//invalid
}

I'd go with your idea of using LastIndexOf ".pdf" and then count backwards. Or use the Path.GetFileNameWithoutExtension method to just get the name and then take the last 10 characters.
These methods will both keep working if the path to the filenames ever changes (which it probably will) and don't rely on magic numbers (other than the one that defines the length of the substring we are interested in) to find the right place in the string.

Related

Contains doen't check in the date range

I have a date range come like this,
string ActualReleaseDates ="7/8/2016, 7/9/2016, 7/11/2016,7/3/2016,7/10/2016,7/17/2016,7/24/2016,7/31/2016";
string NewsReleasedDate ="07/11/2016";
I want to check NewsReleaseDate is inside the ActualReleaseDates
But in the following code it return as a false.
if (ActualReleaseDates.Split(',').Contains(NewsReleasedDate.TrimStart(new Char[] { '0' })))
{
//some code here
}
The immediate problem is that after splitting your ActualReleaseDates string, there isn't an entry of "7/11/2016"... instead, there's an entry of " 7/11/2016"... note the space.
But more fundamentally, just trimming the start of NewsReleasedDate won't help if the value is something like "07/08/2016"... what you should be doing is handling these values as dates, rather than as strings:
Split ActualReleaseDates by comma, then parse each value (after trimming whitespace) in an appropriate format (which I suspect is M/d/yyyy) so that you get a List<DateTime>.
Parse NewsReleasedDate in the appropriate format, which I suspect is MM/dd/yyyy, so you get a DateTime.
See whether the parsed value from the second step occurs in the list from the first step.
(I'd personally recommend using Noda Time and parsing to LocalDate values, but I'm biased...)
Fundamentally, you're trying to see whether one date occurs in a list of dates... so make sure you get your data into its most appropriate representation as early as possible. Ideally, avoid using strings for this at all... we don't know where your data has come from, but if it started off in another representation and was converted into text, see if you can avoid that conversion.
The white space problem. You can use trim() and ' 7/11/2016' will be '7/11/2016'
var ActualReleaseDates = "7/8/2016, 7/9/2016, 7/11/2016,7/3/2016,7/10/2016,7/17/2016,7/24/2016,7/31/2016";
var NewsReleasedDate = "07/11/2016";
var splitActualReleaseDates = ActualReleaseDates.Split(',').Select(x => x.Trim());
if (splitActualReleaseDates.Contains(NewsReleasedDate.TrimStart(new Char[] { '0' })))
{
}
You can use linq to convert your strings into DateTime objects and compare them instead of strings
string ActualReleaseDates ="7/8/2016,7/9/2016,7/11/2016,7/3/2016,7/10/2016,7/17/2016,7/24/2016,7/31/2016";
string NewsReleasedDate ="07/11/2016";
var releaseDates = ActualReleaseDates.Split(',').Select(x => DateTime.Parse(x));
var newsReleased = DateTime.Parse(NewsReleaseDate);
if (releaseDates.Contains(newsReleased))
{
//some code here
}
please note that DateTime is parsed respectively to the current Culture. You can use DateTime.ParseExact if you want to specify exact date format.
You can Prase to DateTime before doing the query like this:
(I think this is the most accurate and guaranteed way to compare dates)
Func<string, DateTime> stringToDate = s => DateTime.ParseExact(s.Trim(), "M/d/yyyy",
CultureInfo.InvariantCulture);
DateTime newReleaseDateTime = stringToDate(NewsReleasedDate);
bool result = ActualReleaseDates.Split(',').Select(x => stringToDate(x))
.Contains(newReleaseDateTime);
It returns false because of the date 07/11/2016 stored in NewsReleasedDate is stored as string with a '0' at the begining. And in the ActualReleaseDates string you have white spaces between the ',' and numbers.
Try to rewrite theese strings like this :
ActualReleaseDates ="7/8/2016,7/9/2016,7/11/2016,7/3/2016,7/10/2016,7/17/2016,7/24/2016,7/31/2016"; // white spaces removed.
and the variable like this :
NewsReleasedDate ="7/11/2016"; // 0 removed
This is my code example :
string ActualReleaseDates = "7/8/2016,7/9/2016,7/11/2016,7/3/2016,7/10/2016,7/17/2016,7/24/2016,7/31/2016";
string NewsReleasedDate = "7/11/2016";
string[] dates = ActualReleaseDates.Split(',');
Console.WriteLine(dates.Contains(NewsReleasedDate));
This is not the best way to compare dates, you can use Date class which is usefull to do this kind of comparations.

Get only numbers from line in file

So I have this file with a number that I want to use.
This line is as follows:
TimeAcquired=1433293042
I only want to use the number part, but not the part that explains what it is.
So the output is:
1433293042
I just need the numbers.
Is there any way to do this?
Follow these steps:
read the complete line
split the line at the = character using string.Split()
extract second field of the string array
convert string to integer using int.Parse() or int.TryParse()
There is a very simple way to do this and that is to call Split() on the string and take the last part. Like so if you want to keep it as a string:
var myValue = theLineString.Split('=').Last();
If you need this as an integer:
int myValue = 0;
var numberPart = theLineString.Split('=').Last();
int.TryParse(numberPart, out myValue);
string setting=sr.ReadLine();
int start = setting.IndexOf('=');
setting = setting.Substring(start + 1, setting.Length - start);
A good approach to Extract Numbers Only anywhere they are found would be to:
var MyNumbers = "TimeAcquired=1433293042".Where(x=> char.IsDigit(x)).ToArray();
var NumberString = new String(MyNumbers);
This is good when the FORMAT of the string is not known. For instance you do not know how numbers have been separated from the letters.
you can do it using split() function as given below
string theLineString="your string";
string[] collection=theLineString.Split('=');
so your string gets divided in two parts,
i.e.
1) the part before "="
2) the part after "=".
so thus you can access the part by their index.
if you want to access numeric one then simply do this
string answer=collection[1];
try
string t = "TimeAcquired=1433293042";
t= t.replace("TimeAcquired=",String.empty);
After just parse.
int mrt= int.parse(t);

Split and Convert string to double C#

I want to convert string to double.
Here's example of what I do :
string line = "4.1;4.0;4.0;3.8;4.0;4.3;4.2;4.0;";
double[] values = line2.Split(';').Select(double.Parse).ToArray();
But an error appears
Input string was not in a correct format.
When I try
string line2 = "1;2;3;4;5;6;7;8;9;10;11;12";
double[] values = line2.Split(';').Select(double.Parse).ToArray();
It works perfectly fine.
What should be input format for double values to work ?
Your problem is the last semicolon in the first input. The double.Parse method is being passed an empty string. double value2 = double.Parse(""); There are several ways to fix this, I'll outline two here:
Check if the last character in the input is a semicolon, if so, strip it. (This should be self explanatory.)
Use the StringSplitOptions.RemoveEmptyEntries overload.
I prefer the second option, myself. As this also removes issue with two consecutive semicolons.
string line = "4.1;4.0;4.0;3.8;4.0;;4.3;4.2;4.0;";
double[] values = line.Split(new char[]{';'}, StringSplitOptions.RemoveEmptyEntries).Select(double.Parse).ToArray();
Also, just to humour the idea that it could be a culture issue as well; the following code makes adjustments for culture-specific scenarios. The reason for the if check is to save on compute time. It could be removed if you desire, with no harm to the overall affect. (It simply means that the programme will replace . with . in situations where the programme is run on a computer with a culture set to use decimals for separators. This is merely a simple optimization.)
string line = "4.1;4.0;4.0;3.8;4.0;;4.3;4.2;4.0;";
if (CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator != ".")
line = line.Replace(".", CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator);
double[] values = line.Split(new char[]{';'}, StringSplitOptions.RemoveEmptyEntries).Select(s => double.Parse(s)).ToArray();
Another sidebar about the potential for a culture issue: if it were a culture issue, the operation would not have thrown an exception, but instead simply return each digit of the number without separator. (I.e. 41, 40, 40, 38, 40, 43, 42, 40)
Other options:
Use double.TryParse instead.
Use a custom for loop and manually parse your data.
There are likely other options as well that I cannot think of.
Another option would be to use the double.TryParse() method on each item in your split array. This will ensure that each item in the array (empty or not) is a valid double before attempting to add it to the values array.
For example:
string line = "4.1;4.0;4.0;3.8;4.0;4.3;4.2;4.0;";
double temp = 0;
double[] values = line.Split(';')
.Where(item => double.TryParse(item, out temp))
.Select(i => temp).ToArray();

Get characters behind the dot in of a double

I feel like this is a very noob question.. but I just can't get the right statement for it.
For display purposes, I want to split a double in two: the part before the dot and the first two digits after the dot. I need it as a string. Target language: C#.
E.g.: 2345.1234 becomes "2345" and "12"
I know how to get the part before the dot, that's simply:
Math.Floor(value).ToString()
...but what is the right way to get the part "behind the dot"?
There must be some nice way to do that in a simple way...
I can't think of anything else then:
Math.Round(100 * (value - Math.Floor(value))).ToString("00");
I'm sure there is a better way, but I just can't think of it. Anyone?
Regular expressions (regex) is probably you best bet, but using the mod operator may be another valuable solution...
stuffToTheRight = value % 1
Cheers.
//
//Use the Fixed point formatting option. You might have a bit more work to do
//if you need to handle cases where "dot" is not the decimal separator.
//
string s = value.ToString("F2", CultureInfo.InvariantCulture);
var values = s.Split(".");
string v1 = values[0];
string v2 = values[1];
See this link for more about formatting: http://msdn.microsoft.com/en-us/library/dwhawy9k.aspx
Here is some untested code that tries to take current culture into account:
//
//Use the Fixed point formatting option.
//
string s = value.ToString("F2", CultureInfo.CurrentCulture);
var values = s.Split(CultureInfo.NumberFormat.NumberDecimalSeparator);
string v1 = values[0];
string v2 = values[1];
use regex ".[0-9][0-9]"
In one line it will be:
string[] vals = value.ToString("f2").Split(CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator.ToCharArray());
vals[0] : before point.
vals[1] : after point.

Remove formatting from a string: "(123) 456-7890" => "1234567890"?

I have a string when a telephone number is inputted - there is a mask so it always looks like "(123) 456-7890" - I'd like to take the formatting out before saving it to the DB.
How can I do that?
One possibility using linq is:
string justDigits = new string(s.Where(c => char.IsDigit(c)).ToArray());
Adding the cleaner/shorter version thanks to craigmoliver
string justDigits = new string(s.Where(char.IsDigit).ToArray())
You can use a regular expression to remove all non-digit characters:
string phoneNumber = "(123) 456-7890";
phoneNumber = Regex.Replace(phoneNumber, #"[^\d]", "");
Then further on - depending on your requirements - you can either store the number as a string or as an integer. To convert the number to an integer type you will have the following options:
// throws if phoneNumber is null or cannot be parsed
long number = Int64.Parse(phoneNumber, NumberStyles.Integer, CultureInfo.InvariantCulture);
// same as Int64.Parse, but returns 0 if phoneNumber is null
number = Convert.ToInt64(phoneNumber);
// does not throw, but returns true on success
if (Int64.TryParse(phoneNumber, NumberStyles.Integer,
CultureInfo.InvariantCulture, out number))
{
// parse was successful
}
Since nobody did a for loop.
long GetPhoneNumber(string PhoneNumberText)
{
// Returns 0 on error
StringBuilder TempPhoneNumber = new StringBuilder(PhoneNumberText.Length);
for (int i=0;i<PhoneNumberText.Length;i++)
{
if (!char.IsDigit(PhoneNumberText[i]))
continue;
TempPhoneNumber.Append(PhoneNumberText[i]);
}
PhoneNumberText = TempPhoneNumber.ToString();
if (PhoneNumberText.Length == 0)
return 0;// No point trying to parse nothing
long PhoneNumber = 0;
if(!long.TryParse(PhoneNumberText,out PhoneNumber))
return 0; // Failed to parse string
return PhoneNumber;
}
used like this:
long phoneNumber = GetPhoneNumber("(123) 456-7890");
Update
As pr commented many countries do have zero's in the begining of the number, if you need to support that, then you have to return a string not a long. To change my code to do that do the following:
1) Change function return type from long to string.
2) Make the function return null instead of 0 on error
3) On successfull parse make it return PhoneNumberText
You can make it work for that number with the addition of a simple regex replacement, but I'd look out for higher initial digits. For example, (876) 543-2019 will overflow an integer variable.
string digits = Regex.Replace(formatted, #"\D", String.Empty, RegexOptions.Compiled);
Aside from all of the other correct answers, storing phone numbers as integers or otherwise stripping out formatting might be a bad idea.
Here are a couple considerations:
Users may provide international phone numbers that don't fit your expectations. See these examples So the usual groupings for standard US numbers wouldn't fit.
Users may NEED to provide an extension, eg (555) 555-5555 ext#343 The # key is actually on the dialer/phone, but can't be encoded in an integer. Users may also need to supply the * key.
Some devices allow you to insert pauses (usually with the character P), which may be necessary for extensions or menu systems, or dialing into certain phone systems (eg, overseas). These also can't be encoded as integers.
[EDIT]
It might be a good idea to store both an integer version and a string version in the database. Also, when storing strings, you could reduce all punctuation to whitespace using one of the methods noted above. A regular expression for this might be:
// (222) 222-2222 ext# 333 -> 222 222 2222 # 333
phoneString = Regex.Replace(phoneString, #"[^\d#*P]", " ");
// (222) 222-2222 ext# 333 -> 2222222222333 (information lost)
phoneNumber = Regex.Replace(phoneString, #"[^\d]", "");
// you could try to avoid losing "ext" strings as in (222) 222-2222 ext.333 thus:
phoneString = Regex.Replace(phoneString, #"ex\w+", "#");
phoneString = Regex.Replace(phoneString, #"[^\d#*P]", " ");
Try this:
string s = "(123) 456-7890";
UInt64 i = UInt64.Parse(
s.Replace("(","")
.Replace(")","")
.Replace(" ","")
.Replace("-",""));
You should be safe with this since the input is masked.
You could use a regular expression or you could loop over each character and use char.IsNumber function.
You would be better off using regular expressions. An int by definition is just a number, but you desire the formatting characters to make it a phone number, which is a string.
There are numerous posts about phone number validation, see A comprehensive regex for phone number validation for starters.
As many answers already mention, you need to strip out the non-digit characters first before trying to parse the number. You can do this using a regular expression.
Regex.Replace("(123) 456-7890", #"\D", String.Empty) // "1234567890"
However, note that the largest positive value int can hold is 2,147,483,647 so any number with an area code greater than 214 would cause an overflow. You're better off using long in this situation.
Leading zeros won't be a problem for North American numbers, as area codes cannot start with a zero or a one.
Alternative using Linq:
string phoneNumber = "(403) 259-7898";
var phoneStr = new string(phoneNumber.Where(i=> i >= 48 && i <= 57).ToArray());
This is basically a special case of C#: Removing common invalid characters from a string: improve this algorithm. Where your formatng incl. White space are treated as "bad characters"
'you can use module / inside sub main form VB.net
Public Function ClearFormat(ByVal Strinput As String) As String
Dim hasil As String
Dim Hrf As Char
For i = 0 To Strinput.Length - 1
Hrf = Strinput.Substring(i, 1)
If IsNumeric(Hrf) Then
hasil &= Hrf
End If
Next
Return Strinput
End Function
'you can call this function like this
' Phone= ClearFormat(Phone)
public static string DigitsOnly(this string phoneNumber)
{
return new string(
new[]
{
// phoneNumber[0], (
phoneNumber[1], // 6
phoneNumber[2], // 1
phoneNumber[3], // 7
// phoneNumber[4], )
// phoneNumber[5],
phoneNumber[6], // 8
phoneNumber[7], // 6
phoneNumber[8], // 7
// phoneNumber[9], -
phoneNumber[10], // 5
phoneNumber[11], // 3
phoneNumber[12], // 0
phoneNumber[13] // 9
});
}

Categories

Resources