By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
440,375 Members | 1,095 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 440,375 IT Pros & Developers. It's quick & easy.

A LINQ way of converting text containing decimals to int?

P: n/a
Refer to Int32.TryParse method: http://msdn.microsoft.com/en-us/library/zf50za27.aspx
if you have to, specifically this example:

numericString = "10345.72"
styles = NumberStyles.Integer Or NumberStyles.AllowDecimalPoint
CallTryParse(numericString, styles)

Which failed to convert the string "10345.72" to the int 10345,
because of the extra digits after the "."

My question is this: is there a neat "LINQ" type way of parsing such
a string so that the first time a "." (period) is found, the string is
extracted, and then I can use Int32.TryParse?

I know I can solve this problem using a character buffer, reading each
Unicode byte into the buffer, then stopping the first time I find a
".", then reading out the buffer to create a string, then using
Int32.TryParse to extract the int from the string. That is, perhaps I
can use the StringBuilder method to CopyTo a char array, then use a
trick to extract the numeric string before the "."

For example--

StringBuilder sb = new StringBuilder ("10345.72");
int count = sb.Length;

char[] temporary_charBuf1 = new char[100]; // 1 of 2

sb.Copy(0,temporary_charBuf1,0,count);

char[] charBuf2 = new char [100] //2 of 2

foreach (char c in temporary_charBuf) {//code here: if char is not a
period, fill charBuf2, otherwise not and break once a period is found}

string numericString = "";

numericString = new string(charBuf2); // Create new string passing
charBuf2 into the constructor

Now your numericString should be 10345 from the original string
"10345.72".

But I'm looking for a faster or shorter way (since this is not a big
deal, and I don't want to spend too many lines of code making it
work). As you can see from the above, which does not even include the
code inside the foreach loop, it's a lot of code.

Can we replace this with one line of LINQ (plus I'm trying to learn
LINQ as I go)?
No big deal (pseudo code is OK)...just curious.

RL
Sep 1 '08 #1
Share this Question
Share on Google+
13 Replies


P: n/a
raylopez99 <ra********@yahoo.comwrote:

<snip>
Can we replace this with one line of LINQ (plus I'm trying to learn
LINQ as I go)?
No big deal (pseudo code is OK)...just curious.
You *could* do it with LINQ, but it would be painfully slow and
unreadable. Here's a simpler method to do it:

public int ParseInt32BeforePeriod(string text)
{
int periodIndex = text.IndexOf('.');
if (periodIndex != -1)
{
text = text.Substring(0, periodIndex);
}
return int.Parse(text);
}

(You can turn it into a TryParseInt32BeforePeriod taking an out
parameter and returning a boolean pretty easily, if you want.)

--
Jon Skeet - <sk***@pobox.com>
Web site: http://www.pobox.com/~skeet
Blog: http://www.msmvps.com/jon.skeet
C# in Depth: http://csharpindepth.com
Sep 1 '08 #2

P: n/a
raylopez99 wrote:
Refer to Int32.TryParse method: http://msdn.microsoft.com/en-us/library/zf50za27.aspx
if you have to, specifically this example:

numericString = "10345.72"
styles = NumberStyles.Integer Or NumberStyles.AllowDecimalPoint
CallTryParse(numericString, styles)

Which failed to convert the string "10345.72" to the int 10345,
because of the extra digits after the "."

My question is this: is there a neat "LINQ" type way of parsing such
a string so that the first time a "." (period) is found, the string is
extracted, and then I can use Int32.TryParse?
int result = (int)Math.Floor(decimal.Parse("10345.72"));

Alun Harford
Sep 1 '08 #3

P: n/a


Alun Harford wrote:
>
int result = (int)Math.Floor(decimal.Parse("10345.72"));
Cripes, is that legal? My gawd, it is. That's brilliant.

RL
Sep 1 '08 #4

P: n/a


Jon Skeet [ C# MVP ] wrote:
>
(You can turn it into a TryParseInt32BeforePeriod taking an out
parameter and returning a boolean pretty easily, if you want.)
Yes, please, I want. If you have a moment, as a learning exercise for
me it would be helpful. Just the other day in fact I did not realize
that with ref 'out' parameter you don't need to initialize the 'out'
parameter, it just magically shows up, if at all, when the function
runs, so it would be helpful to see another example of this.

BTW I did try the char[] to string conversion mentioned in the
original post and it worked, here is the format.

char[] charBuf; string hiString;
public myForm() {
InitializeComponent();
StringBuilder sb = new StringBuilder("hi there!"); //what
is to be converted to char
int count0 = sb.Length;
charBuf = new char[count0]; // char array, holds chars
h,i, , t,h,e,r,e,!
//can be any size big enough, but if you make it too big it gets
filled with blanks anyway
sb.CopyTo(0, charBuf, 0, count0);
hiString = new string(charBuf); //should be string "hi
there!; Yes, works.
}
Sep 1 '08 #5

P: n/a
On Sep 2, 12:45*am, raylopez99 <raylope...@yahoo.comwrote:
(You can turn it into a TryParseInt32BeforePeriod taking an out
parameter and returning a boolean pretty easily, if you want.)

Yes, please, I want. *If you have a moment, as a learning exercise for
me it would be helpful.
public bool ParseInt32BeforePeriod(string text, out value)
{
int periodIndex = text.IndexOf('.');
if (periodIndex != -1)
{
text = text.Substring(0, periodIndex);
}
return int.TryParse(text, out value);
}

<snip>
BTW I did try the char[] to string conversion mentioned in the
original post and it worked, here is the format.
You may be interested to know that the String.ToCharArray() method
does the same thing.

Jon
Sep 2 '08 #6

P: n/a
On Sep 2, 12:24*am, raylopez99 <raylope...@yahoo.comwrote:
int result = (int)Math.Floor(decimal.Parse("10345.72"));

Cripes, is that legal? *My gawd, it is. *That's brilliant.
Out of interest, which bit did you expect to be illegal?

It will work with non-negative decimals, but would fail for either
"-3.4" (returning -4) or "3.wibble". These may not be a problem for
you, of course, but it's worth being aware of them.

Jon
Sep 2 '08 #7

P: n/a
Jon Skeet [C# MVP] wrote:
On Sep 2, 12:24 am, raylopez99 <raylope...@yahoo.comwrote:
>>int result = (int)Math.Floor(decimal.Parse("10345.72"));
Cripes, is that legal? My gawd, it is. That's brilliant.

Out of interest, which bit did you expect to be illegal?

It will work with non-negative decimals, but would fail for either
"-3.4" (returning -4) or "3.wibble". These may not be a problem for
you, of course, but it's worth being aware of them.
Good point.

How about:

int result = int.Parse(
new string("10345.72".ToCharArray().TakeWhile(c =c != '.')
.ToArray()));

Alun Harford
Sep 2 '08 #8

P: n/a
Alun Harford <de*****@alunharford.co.ukwrote:
It will work with non-negative decimals, but would fail for either
"-3.4" (returning -4) or "3.wibble". These may not be a problem for
you, of course, but it's worth being aware of them.

Good point.

How about:

int result = int.Parse(
new string("10345.72".ToCharArray().TakeWhile(c =c != '.')
.ToArray()));
Yup, that's about what I'd come up with if we were absolutely
*desperate* for a LINQ solution - although as String implements
IEnumerable<charalready, there's no need to call ToCharArray. It's
pretty icky though :)

--
Jon Skeet - <sk***@pobox.com>
Web site: http://www.pobox.com/~skeet
Blog: http://www.msmvps.com/jon.skeet
C# in Depth: http://csharpindepth.com
Sep 2 '08 #9

P: n/a
On Sep 1, 11:00*pm, "Jon Skeet [C# MVP]" <sk...@pobox.comwrote:
On Sep 2, 12:45*am, raylopez99 <raylope...@yahoo.comwrote:
(You can turn it into a TryParseInt32BeforePeriod taking an out
parameter and returning a boolean pretty easily, if you want.)
Yes, please, I want. *If you have a moment, as a learning exercise for
me it would be helpful.

public bool ParseInt32BeforePeriod(string text, out value)
{
* * int periodIndex = text.IndexOf('.');
* * if (periodIndex != -1)
* * {
* * * * text = text.Substring(0, periodIndex);
* * }
* * return int.TryParse(text, out value);

}

<snip>
public bool ParseInt32BeforePeriod(string text, out value) //
<--compiler says an error here
{
int periodIndex = text.IndexOf('.');
if (periodIndex != -1)
{
text = text.Substring(0, periodIndex);
}
return int.TryParse(text, out value);
}

This failed to compile: "error CS1001: Identifier expected" and it
points to the outer parens at the arrow above. Any idea why?

Also, how do you actually use this in main()? is it something like:

anObject myObject = new anObject();
int myint;
if (myObject.ParseInt32BeforePeriod("12345.54", value){ myint =
value;} //??

RL
Sep 2 '08 #10

P: n/a
raylopez99 <ra********@yahoo.comwrote:
public bool ParseInt32BeforePeriod(string text, out value) //
<--compiler says an error here
Sorry, "out int value".

That's what I get for not compiling the app. (I was writing that post
on the train, on a pretty weak laptop which takes a while to do
anything...)
This failed to compile: "error CS1001: Identifier expected" and it
points to the outer parens at the arrow above. Any idea why?
Yup, it thinks that "value" of the
Also, how do you actually use this in main()? is it something like:

anObject myObject = new anObject();
int myint;
if (myObject.ParseInt32BeforePeriod("12345.54", value){ myint =
value;} //??
You'd do:

anObject myObject = new anObject(); // Or just make it a static method
int myInt;
if (myObject.ParseInt32BeforePeriod("12345.54", out myInt))
{
// Use myInt here
}

If you look at P131-133 of C# in Depth you'll find an alternative way
of representing this.

--
Jon Skeet - <sk***@pobox.com>
Web site: http://www.pobox.com/~skeet
Blog: http://www.msmvps.com/jon.skeet
C# in Depth: http://csharpindepth.com
Sep 2 '08 #11

P: n/a
On Sep 2, 3:23*pm, Jon Skeet [C# MVP] <sk...@pobox.comwrote:
You'd do:

anObject myObject = new anObject(); // Or just make it a static method
int myInt;
if (myObject.ParseInt32BeforePeriod("12345.54", out myInt))
{
* * // Use myInt here

}
Just compiled it, and it works perfectly. Thanks. Into my form
library it goes for future reference, might even warrant a hardcopy
for the binder...done.
>
If you look at P131-133 of C# in Depth you'll find an alternative way
of representing this.
OK, but I'm only up to page 34.

Good night and good fight (I'm a couple of hours ahead of you... 1:30
AM here)

RL
Sep 2 '08 #12

P: n/a
Alun Harford wrote:
raylopez99 wrote:
>Refer to Int32.TryParse method:
http://msdn.microsoft.com/en-us/library/zf50za27.aspx
if you have to, specifically this example:

numericString = "10345.72"
styles = NumberStyles.Integer Or NumberStyles.AllowDecimalPoint
CallTryParse(numericString, styles)

Which failed to convert the string "10345.72" to the int 10345,
because of the extra digits after the "."

My question is this: is there a neat "LINQ" type way of parsing such
a string so that the first time a "." (period) is found, the string is
extracted, and then I can use Int32.TryParse?

int result = (int)Math.Floor(decimal.Parse("10345.72"));
Math.Floor should not be necessary.

int result = (int)decimal.Parse("10345.72");

Arne
Sep 6 '08 #13

P: n/a
Jon Skeet [C# MVP] wrote:
You *could* do it with LINQ, but it would be painfully slow and
unreadable. Here's a simpler method to do it:

public int ParseInt32BeforePeriod(string text)
{
int periodIndex = text.IndexOf('.');
if (periodIndex != -1)
{
text = text.Substring(0, periodIndex);
}
return int.Parse(text);
}

(You can turn it into a TryParseInt32BeforePeriod taking an out
parameter and returning a boolean pretty easily, if you want.)
IndexOf and Substring reminds me too much of strstr and strncpy.
And it is pretty well camouflaged culture invariant !

Either Alan's (int)decimal.Parse(s) or a regex like
int.Parse(Regex.Match(s, @"\d+").Value) would be better
in my opinion.

Arne

Sep 6 '08 #14

This discussion thread is closed

Replies have been disabled for this discussion.