Split a string and convert one of the index as int - c#

I have the following code:
static void Main(string[] args)
{
string prueba = "Something_2.zip";
int num;
prueba = prueba.Split('.')[0];
if (!prueba.Contains("_"))
{
prueba = prueba + "_";
}
else
{
//The code I want to try
}
}
The idea is that in the else I want to split the string after the _ and convert it to int, I did this like
num = Convert.ToInt16(prueba.Split('_')[1]);
but can I cast the split? for example num = (int)(prueba.Split('_')[1]);
Is it possible to do it that way? Or I have to use the Convert?

You Cannot cast string as integer, so you need to do some conversion:
I suggest you to use Int.TryParse() in this scenario.
Hence the else part will be like the following:
else
{
if(int.TryParse(prueba.Substring(prueba.LastIndexOf('_')),out num))
{
//proceed your code
}
else
{
//Throw error message
}
}

Convert the string to int like this:
var myInt = 0;
if (Int32.TryParse(prueba.Split('_')[1], out myInt))
{
// use myInt here
}

It's a string, so you'll have to parse it. You can use Convert.ToInt32, int.Parse, or int.TryParse to do so, like so:
var numString = prueba.Split('_')[1];
var numByConvert = Convert.ToInt32(numString);
var numByParse = int.Parse(numString);
int numByTryParse;
if(int.TryParse(numString, out numByTryParse))
{/*Success, numByTryParse is populated with the numString's int value.*/}
else
{/*Failure. You can handle the fact that it failed to parse now. numByTryParse will be 0 */}

string prueba = "Something_2.zip";
prueba = prueba.Split('.')[0];
int theValue = 0; // Also default value if no '_' is found
var index = prueba.LastIndexOf('_');
if(index >= 0)
int.TryParse(prueba.Substring(index + 1), out theValue);
theValue.Dump();

You could use a regular expression and avoid all the string splitting logic. If you need an explanation of the regex I've used see https://regex101.com/r/fW9fX5/1
var num = -1; // set to default value that you intend to use when the string doesn't contain an underscore
var fileNamePattern = new Regex(#".*_(?<num>\d+)\..*");
var regexMatch = fileNamePattern.Match("Something_2.zip");
if (regexMatch.Success)
{
int.TryParse(regexMatch.Groups["num"].Value, out num);
}

Related

How to convert a string with comma to integer in C#

For example I have a string "99,999 ABC XYZ"
Now I want to convert to integer "99999"
I have made a code that worked:
var regex = new Regex("[A-z]");
linksOnPage = regex.Replace(linksOnPage, "");
regex = new Regex(" ");
linksOnPage = regex.Replace(linksOnPage, "");
int noPage = int.Parse(regex.Replace(linksOnPage, ""),
NumberStyles.AllowThousands);
But I feel it's not good enough, can anyone help me to make it shorter?
This Regex will remove all the letters and spaces:
var regex = new Regex(" |[A-z]");
linksOnPage = regex.Replace(linksOnPage, "");
You could use int.Parse and add the NumberStyles.AllowThousands flag:
int num = int.Parse(linksOnPage , NumberStyles.AllowThousands);
Or int.TryParse letting you know if the operation succeeded:
int num;
if (int.TryParse(linksOnPage , NumberStyles.AllowThousands,
CultureInfo.InvariantCulture, out num))
{
// parse successful, use 'num'
}
Or you can also try this:
int num = int.Parse(linksOnPage.Replace(",", ""));
This would be my approach, it's not really shorter though:
public static void Main(string[] args)
{
string input = "99,999 ABC XYZ";
var chars = input.ToCharArray().ToList();
var builder = new StringBuilder();
foreach (var character in chars)
{
if (char.IsNumber(character))
builder.Append(character);
}
int result = 0;
int.TryParse(builder.ToString(), out result);
Console.WriteLine(result);
Console.ReadKey();
}
you could do something like this:
int? ParseIntFromString( string s )
{
Match m = rxInt.Match(s) ;
int? value = m.Success ? int.Parse( m.Value , NumberStyles.AllowLeadingSign|NumberStyles.AllowThousands ) : (int?)null ;
return value ;
}
static Regex rxInt = new Regex( #"^-?\d{1,3}(,\d\d\d)*");
the return value is null if no integer value was found and the parsed value if it was.
Note that the match is anchored at start-of-string via ^; if you want to match an number anywhere in the string, simply remove it.
You could also kick it old-school and do something like this:
public int? ParseIntFromString( string s )
{
bool found = false ;
int acc = 0 ;
foreach( char c in s.Where( x => char.IsDigit )
{
found = true ;
acc += c - '0' ;
}
return found ? (int?)acc : (int?) null ;
}

How can i parse/get only the number inside the string/s?

The variable PostedId contain for example 7 strings.
For example in index 0 i see: {"id":"1234567890"}
I want in the loop FOR
To parse/extract from the current index string only the number.
So in the line :
objFacebookClient.Delete(PostedId[i]).ToString();
Instead PostedId[i] will be {"id":"1234567890"} it should be only: 1234567890 only the number.
private void button7_Click(object sender, EventArgs e)
{
var responsePost = "";
try
{
var objFacebookClient = new FacebookClient(AccessPageToken);
for (int i = 0; i < PostedId.Count; i++)
{
objFacebookClient.Delete(PostedId[i]).ToString();
}
}
catch (Exception ex)
{
responsePost = "Facebook Posting Error Message: " + ex.Message;
}
}
If I understand your question correctly, you want to get numbers in your string then parsing them to int.
If it is, you can use Char.IsDigit method to get numbers inside a string and use Int32.TryParse method to parsing it.
For example;
string s = "{\"id\":\"1234567890\"}";
char[] array = s.Where(c => Char.IsDigit(c)).ToArray();
string s1 = new string(array);
int i;
if (Int32.TryParse(s1, NumberStyles.Integer, CultureInfo.InvariantCulture, out i))
{
Console.WriteLine(i);
}
Output will be;
1234567890
Here a demonstration.
Based on your comment under Soner Gönül`s answer, you probably want to do something like this.
This is a modification of that answer; just outputting the resulting string, without parsing it to an int, which obviously will not work when including "_".
Please make sure you include details like this in your original post in future questions.
string input = "{\"id\":\"12345_67890\"}";
char[] array = input.Where(c => Char.IsDigit(c) || c == '_').ToArray();
// Will contain: "12345_67890"
string result = new string(array);
Should be easy enough to do with a string.split or making use of a regex to extract the number part of the id. I can give an example if needed
The format you have here is looks like Json.
You can use
JSON.NET to parse your string.
Make class called for example 'FaceBookResponse':
public class FaceBookResponse{
public int id { get; set; }
}
Then use JavaScriptSerializer (Reference System.Web.Extensions):
JavaScriptSerializer serializer = new JavaScriptSerializer();
In the for loop use this:
var obj = serializer.Deserialize<FaceBookResponse>();
objFacebookClient.Delete(obj.id).ToString();
you can use regx for this,
5 is minimum digits you want,
numberonly is output, strText is input text
Regex _Regex = new Regex("\\d{5,}", RegexOptions.IgnoreCase);
MatchCollection matchList = _Regex.Matches(strText);
string NumberOnly = string.Empty;
if (matchList.Count == 0)
NumberOnly = matchList(0).ToString();
//if strText = "Test12345Test6789"
//Output will be
//matchList(0) = 12345
//matchList(1) = 6789

How to cast string to int

I have a set of objects named something like this:
_1,_2,_3 .... _n
Isn't an array, just a bunch of objects uinto a custom control. I want to cast the name to an int. first I remove _, but If use
private void Superficie_MouseDown(object sender, MouseButtonEventArgs e)
{
int index = 0;
Shape myShape = ((Shape)sender);
string lcNombre = myShape.Name.Remove(0, 1);
//--------------------------------------------------------------------
// Those are my tryes
// Doesn't work because it must expect a nullable value
index = lcNombre as decimal;
// Doesn't work Can't convert string to int
index = (int)lcNombre;
//--------------------------------------------------------------------
if (index > 0)
{
bool lIsSelected = !Pieza.Superficies.Where(x=>x.Id == index).First().IsSelected;
Pieza.Superficies.Where(x => x.Id == index).First().IsSelected = lIsSelected;
if (lIsSelected)
myShape.Fill = new SolidColorBrush(SystemColors.HotTrackColor);
else
myShape.Fill = new SolidColorBrush(SystemColors.ControlLightLightColor);
}
}
How can I do to cast it ?
The most straightforward way is
index = int.Parse(lcNombre);
If you're not completely sure whether lcNombre is really an integer, you can use instead
int result;
bool isInt = int.TryParse(lcNobre, out result);
or in newer versions of .NET, you can declare the output variable like:
bool isInt = int.TryParse(lcNobre, out var result);
Finally you can use
index = Convert.ToInt32(lcNobre);
This approach (like int.Parse()) will throw a FormatException if the input value is not convertible to an integer.
You can also use the Convert static methods:
index = Convert.ToInt32(lcNombre);
MSDN Link: http://msdn.microsoft.com/en-us/library/sf1aw27b(v=vs.110).aspx
Error wise.. you may want to use TryParse.. as it returns true or false depending on a successful conversion:
int index;
if (int.TryParse(lcNombre, out index)) {
// conversion successful
}
else {
// couldn't convert
}
MSDN Link for int.TryParse: http://msdn.microsoft.com/en-us/library/f02979c7(v=vs.110).aspx
try this
int result=0;
Int32.TryParse(lcNombre,out result);
My favorite way to do this is to make an extension method as follows
public static class ExtensionMethods
{
public static int? AsInteger( this string str)
{
int value;
if ( int.TryParse( str, out value ) )
{
return value;
}
else
{
return null;
}
}
}
then you can this
index = lcNombre.AsInteger() ?? 0;
string strArr[] = myShape.Name.Split('_',StringSplitOptions.RemoveEmptyEntries)
int num;
int.TryParse(strArr[0],num);

compare the characters in two strings

In C#, how do I compare the characters in two strings.
For example, let's say I have these two strings
"bc3231dsc" and "bc3462dsc"
How do I programically figure out the the strings
both start with "bc3" and end with "dsc"?
So the given would be two variables:
var1 = "bc3231dsc";
var2 = "bc3462dsc";
After comparing each characters from var1 to var2, I would want the output to be:
leftMatch = "bc3";
center1 = "231";
center2 = "462";
rightMatch = "dsc";
Conditions:
1. The strings will always be a length of 9 character.
2. The strings are not case sensitive.
The string class has 2 methods (StartsWith and Endwith) that you can use.
After reading your question and the already given answers i think there are some constraints are missing, which are maybe obvious to you, but not to the community. But maybe we can do a little guess work:
You'll have a bunch of string pairs that should be compared.
The two strings in each pair are of the same length or you are only interested by comparing the characters read simultaneously from left to right.
Get some kind of enumeration that tells me where each block starts and how long it is.
Due to the fact, that a string is only a enumeration of chars you could use LINQ here to get an idea of the matching characters like this:
private IEnumerable<bool> CommonChars(string first, string second)
{
if (first == null)
throw new ArgumentNullException("first");
if (second == null)
throw new ArgumentNullException("second");
var charsToCompare = first.Zip(second, (LeftChar, RightChar) => new { LeftChar, RightChar });
var matchingChars = charsToCompare.Select(pair => pair.LeftChar == pair.RightChar);
return matchingChars;
}
With this we can proceed and now find out how long each block of consecutive true and false flags are with this method:
private IEnumerable<Tuple<int, int>> Pack(IEnumerable<bool> source)
{
if (source == null)
throw new ArgumentNullException("source");
using (var iterator = source.GetEnumerator())
{
if (!iterator.MoveNext())
{
yield break;
}
bool current = iterator.Current;
int index = 0;
int length = 1;
while (iterator.MoveNext())
{
if(current != iterator.Current)
{
yield return Tuple.Create(index, length);
index += length;
length = 0;
}
current = iterator.Current;
length++;
}
yield return Tuple.Create(index, length);
}
}
Currently i don't know if there is an already existing LINQ function that provides the same functionality. As far as i have already read it should be possible with SelectMany() (cause in theory you can accomplish any LINQ task with this method), but as an adhoc implementation the above was easier (for me).
These functions could then be used in a way something like this:
var firstString = "bc3231dsc";
var secondString = "bc3462dsc";
var commonChars = CommonChars(firstString, secondString);
var packs = Pack(commonChars);
foreach (var item in packs)
{
Console.WriteLine("Left side: " + firstString.Substring(item.Item1, item.Item2));
Console.WriteLine("Right side: " + secondString.Substring(item.Item1, item.Item2));
Console.WriteLine();
}
Which would you then give this output:
Left side: bc3
Right side: bc3
Left side: 231
Right side: 462
Left side: dsc
Right side: dsc
The biggest drawback is in someway the usage of Tuple cause it leads to the ugly property names Item1 and Item2 which are far away from being instantly readable. But if it is really wanted you could introduce your own simple class holding two integers and has some rock-solid property names. Also currently the information is lost about if each block is shared by both strings or if they are different. But once again it should be fairly simply to get this information also into the tuple or your own class.
static void Main(string[] args)
{
string test1 = "bc3231dsc";
string tes2 = "bc3462dsc";
string firstmatch = GetMatch(test1, tes2, false);
string lasttmatch = GetMatch(test1, tes2, true);
string center1 = test1.Substring(firstmatch.Length, test1.Length -(firstmatch.Length + lasttmatch.Length)) ;
string center2 = test2.Substring(firstmatch.Length, test1.Length -(firstmatch.Length + lasttmatch.Length)) ;
}
public static string GetMatch(string fist, string second, bool isReverse)
{
if (isReverse)
{
fist = ReverseString(fist);
second = ReverseString(second);
}
StringBuilder builder = new StringBuilder();
char[] ar1 = fist.ToArray();
for (int i = 0; i < ar1.Length; i++)
{
if (fist.Length > i + 1 && ar1[i].Equals(second[i]))
{
builder.Append(ar1[i]);
}
else
{
break;
}
}
if (isReverse)
{
return ReverseString(builder.ToString());
}
return builder.ToString();
}
public static string ReverseString(string s)
{
char[] arr = s.ToCharArray();
Array.Reverse(arr);
return new string(arr);
}
Pseudo code of what you need..
int stringpos = 0
string resultstart = ""
while not end of string (either of the two)
{
if string1.substr(stringpos) == string1.substr(stringpos)
resultstart =resultstart + string1.substr(stringpos)
else
exit while
}
resultstart has you start string.. you can do the same going backwards...
Another solution you can use is Regular Expressions.
Regex re = new Regex("^bc3.*?dsc$");
String first = "bc3231dsc";
if(re.IsMatch(first)) {
//Act accordingly...
}
This gives you more flexibility when matching. The pattern above matches any string that starts in bc3 and ends in dsc with anything between except a linefeed. By changing .*? to \d, you could specify that you only want digits between the two fields. From there, the possibilities are endless.
using System;
using System.Text.RegularExpressions;
using System.Collections.Generic;
class Sample {
static public void Main(){
string s1 = "bc3231dsc";
string s2 = "bc3462dsc";
List<string> common_str = commonStrings(s1,s2);
foreach ( var s in common_str)
Console.WriteLine(s);
}
static public List<string> commonStrings(string s1, string s2){
int len = s1.Length;
char [] match_chars = new char[len];
for(var i = 0; i < len ; ++i)
match_chars[i] = (Char.ToLower(s1[i])==Char.ToLower(s2[i]))? '#' : '_';
string pat = new String(match_chars);
Regex regex = new Regex("(#+)", RegexOptions.Compiled);
List<string> result = new List<string>();
foreach (Match match in regex.Matches(pat))
result.Add(s1.Substring(match.Index, match.Length));
return result;
}
}
for UPDATE CONDITION
using System;
class Sample {
static public void Main(){
string s1 = "bc3231dsc";
string s2 = "bc3462dsc";
int len = 9;//s1.Length;//cond.1)
int l_pos = 0;
int r_pos = len;
for(int i=0;i<len && Char.ToLower(s1[i])==Char.ToLower(s2[i]);++i){
++l_pos;
}
for(int i=len-1;i>0 && Char.ToLower(s1[i])==Char.ToLower(s2[i]);--i){
--r_pos;
}
string leftMatch = s1.Substring(0,l_pos);
string center1 = s1.Substring(l_pos, r_pos - l_pos);
string center2 = s2.Substring(l_pos, r_pos - l_pos);
string rightMatch = s1.Substring(r_pos);
Console.Write(
"leftMatch = \"{0}\"\n" +
"center1 = \"{1}\"\n" +
"center2 = \"{2}\"\n" +
"rightMatch = \"{3}\"\n",leftMatch, center1, center2, rightMatch);
}
}

formatting string in MVC /C#

I have a string 731478718861993983 and I want to get this 73-1478-7188-6199-3983 using C#. How can I format it like this ?
Thanks.
By using regex:
public static string FormatTest1(string num)
{
string formatPattern = #"(\d{2})(\d{4})(\d{4})(\d{4})(\d{4})";
return Regex.Replace(num, formatPattern, "$1-$2-$3-$4-$5");
}
// test
string test = FormatTest1("731478718861993983");
// test result: 73-1478-7188-6199-3983
If you're dealing with a long number, you can use a NumberFormatInfo to format it:
First, define your NumberFormatInfo (you may want additional parameters, these are the basic 3):
NumberFormatInfo format = new NumberFormatInfo();
format.NumberGroupSeparator = "-";
format.NumberGroupSizes = new[] { 4 };
format.NumberDecimalDigits = 0;
Next, you can use it on your numbers:
long number = 731478718861993983;
string formatted = number.ToString("n", format);
Console.WriteLine(formatted);
After all, .Net has very good globalization support - you're better served using it!
string s = "731478718861993983"
var newString = (string.Format("{0:##-####-####-####-####}", Convert.ToInt64(s));
LINQ-only one-liner:
var str = "731478718861993983";
var result =
new string(
str.ToCharArray().
Reverse(). // So that it will go over string right-to-left
Select((c, i) => new { #char = c, group = i / 4}). // Keep group number
Reverse(). // Restore original order
GroupBy(t => t.group). // Now do the actual grouping
Aggregate("", (s, grouping) => "-" + new string(
grouping.
Select(gr => gr.#char).
ToArray())).
ToArray()).
Trim('-');
This can handle strings of arbitrary lenghs.
Simple (and naive) extension method :
class Program
{
static void Main(string[] args)
{
Console.WriteLine("731478718861993983".InsertChar("-", 4));
}
}
static class Ext
{
public static string InsertChar(this string str, string c, int i)
{
for (int j = str.Length - i; j >= 0; j -= i)
{
str = str.Insert(j, c);
}
return str;
}
}
If you're dealing strictly with a string, you can make a simple Regex.Replace, to capture each group of 4 digits:
string str = "731478718861993983";
str = Regex.Replace(str, "(?!^).{4}", "-$0" ,RegexOptions.RightToLeft);
Console.WriteLine(str);
Note the use of RegexOptions.RightToLeft, to start capturing from the right (so "12345" will be replaced to 1-2345, and not -12345), and the use of (?!^) to avoid adding a dash in the beginning.
You may want to capture only digits - a possible pattern then may be #"\B\d{4}".
string myString = 731478718861993983;
myString.Insert(2,"-");
myString.Insert(7,"-");
myString.Insert(13,"-");
myString.Insert(18,"-");
My first thought is:
String s = "731478718861993983";
s = s.Insert(3,"-");
s = s.Insert(8,"-");
s = s.Insert(13,"-");
s = s.Insert(18,"-");
(don't remember if index is zero-based, in which case you should use my values -1)
but there is probably some easier way to do this...
If the position of "-" is always the same then you can try
string s = "731478718861993983";
s = s.Insert(2, "-");
s = s.Insert(7, "-");
s = s.Insert(12, "-");
s = s.Insert(17, "-");
Here's how I'd do it; it'll only work if you're storing the numbers as something which isn't a string as they're not able to be used with format strings.
string numbers = "731478718861993983";
string formattedNumbers = String.Format("{0:##-####-####-####-####}", long.Parse(numbers));
Edit: amended code, since you said they were held as a string in your your original question

Categories