Formating string from List<T> - c#

I have a class with List
public class PolynomialCoefficients<T> : IEnumerable<T>
{
private List<T> coefficients;
public string ToString(string format)
{
StringBuilder polynomialString = new StringBuilder();
char separator = ':';
foreach(T coefficient in coefficients)
{
polynomialString.Append(String.Format("0.0000", coefficient.ToString()));
polynomialString.Append(separator);
}
polynomialString.Remove(polynomialString.Length - 1, 1);
return polynomialString.ToString();
}
}
Lets say that list contains elements: 1,2,3
I want to call
ToString("0.000")
and get output: 1.000:2.000:3.000
but every time output is similar to 0.000:0.000:0.000

String.Format needs a very specific kind of string. You gave it a literal string to print:
String.Format("0.0000", coefficient.ToString());
So it just printed it. If you had given it a placeholder:
String.Format("{0}", coefficient.ToString("0.0000"));
It would have substituted the passed argument in. You can also specify the format of the placeholder:
String.Format("{0:f4}", coefficient);
"f4" would give you your format. The standard formatting strings can be found on MSDN

First, you don't need a ToString() call on the coefficient.ToString(). Second, your format string is a bit incorrect: you need to use the "{0:0.0000}" form.
And while we're at it, your code can be greatly simplified:
var result = string.Join(";", coefficients.Select(c => string.Format("{0:0.0000}", c));
return result;

public class PolynomialCoefficients<T> : IEnumerable<T>
{
private List<T> coefficients;
public string ToString(string format)
{
const string separator = ":";
return string.Join(separator, coefficients.Select(c => string.Format("{0:f4}", c)));
}
}

The reason is because of call to ToString in String.Format and not specifying the place holder.
String.Format("0.0000", coefficient.ToString())
//^^^^^
String.Format with your format should expect a floating point number, it will not work on string values, for string values, format would be ignored and passed value will be returned.
Also you have to specify the place holder like:
string str = (String.Format("{0:0.0000}", coefficient));
Consider the following example:
String.Format("{0:0.0000}", 1.2345123123) //would return "1.2345"
String.Format("{0:0.0000}", "1.2345123123")//would return "1.2345123123" ignoring the format

You should constrain T to IFormattable:
public class PolynomialCoefficients<T> : IEnumerable<T>
where T : IFormattable
With that you can use coefficient.ToString("0.0000", null) where coefficient is a T. You can also use:
polynomialString.AppendFormat("{0:0.0000}", coefficient)
with your StringBuilder. That will end up calling coefficient.ToString("0.0000", null) as well.

Related

Extracting a substring of variable length from a string

I need to extract a variable length decimal number from a string using c# and .NET. The input string is like $PTNTHPR,352.5,N,2.3,N,4.6,N,16*. I need the first occurrence of decimal number, i.e the 352.5 part. The numerical value ranges from 0.0 to 360.0 and I need that number from that string.
I searched a lot and got solution for a fixed length sub string but here I have variable length to extract. I have not tried with any code yet.
If it is always in this format you can use String.Split and decimal.Parse
var data = #"$PTNTHPR,352.5,N,2.3,N,4.6,N,16*";
var d = decimal.Parse(data.Split(new[]{','})[1]);
Console.WriteLine(d);
This is just a sample code to guide you. You should add additional exception handling logic to this, Also consider using decimal.TryParse
If you want to find the first occurance of decimal value you split the string and parse them one by one.
var data = #"$PTNTHPR,352.5,N,2.3,N,4.6,N,16*";
var splited = data.Split(new[]{','});
decimal? value = null;
foreach (var part in splited)
{
decimal parsed;
if (decimal.TryParse(part, out parsed))
{
value = parsed;
break;
}
}
Console.WriteLine(value);
First occurence in any of the tokens? Use String.Split to separate them and LINQ to find the first. You can use decimal.TryParse to check if it's parsable:
decimal? firstParsableToken = "$PTNTHPR,352.5,N,2.3,N,4.6,N,16*".Split(',')
.Select(s => s.TryGetDecimal(NumberFormatInfo.InvariantInfo))
.FirstOrDefault(d => d.HasValue);
Used this simple extension method to parse it to decimal?:
public static decimal? TryGetDecimal(this string item, IFormatProvider formatProvider = null, NumberStyles nStyles = NumberStyles.Any)
{
if (formatProvider == null) formatProvider = NumberFormatInfo.CurrentInfo;
decimal d = 0m;
bool success = decimal.TryParse(item, nStyles, formatProvider, out d);
if (success)
return d;
else
return null;
}
If the string is always comma separated, can you not use string.Split() to get each section, then use double.TryParse() to test if that part is numeric?
public static class Helper
{
public static string MyExtract(this string s)
{
return s.Split(',').First(str => Regex.IsMatch(str, #"[0-9.,]"));
}
}
Use it like this: string str = "$PTNTHPR,352.5,N,2.3,N,4.6,N,16*".MyExtract();
Then convert it to double/decimal if you need it.

Insert spaces into string using string.format

I've been using C# String.Format for formatting numbers before like this (in this example I simply want to insert a space):
String.Format("{0:### ###}", 123456);
output:
"123 456"
In this particular case, the number is a string. My first thought was to simply parse it to a number, but it makes no sense in the context, and there must be a prettier way.
Following does not work, as ## looks for numbers
String.Format("{0:### ###}", "123456");
output:
"123456"
What is the string equivalent to # when formatting? The awesomeness of String.Format is still fairly new to me.
You have to parse the string to a number first.
int number = int.Parse("123456");
String.Format("{0:### ###}", number);
of course you could also use string methods but that's not as reliable and less safe:
string strNumber = "123456";
String.Format("{0} {1}", strNumber.Remove(3), strNumber.Substring(3));
As Heinzi pointed out, you can not have format specifier for string arguments.
So, instead of String.Format, you may use following:
string myNum="123456";
myNum=myNum.Insert(3," ");
Not very beautiful, and the extra work might outweigh the gains, but if the input is a string on that format, you could do:
var str = "123456";
var result = String.Format("{0} {1}", str.Substring(0,3), str.Substring(3));
string is not a IFormattable
Console.WriteLine("123456" is IFormattable); // False
Console.WriteLine(21321 is IFormattable); // True
No point to supply a format if the argument is not IFormattable only way is to convert your string to int or long
We're doing string manipulation, so we could always use a regex.
Adapted slightly from here:
class MyClass
{
static void Main(string[] args)
{
string sInput, sRegex;
// The string to search.
sInput = "123456789";
// The regular expression.
sRegex = "[0-9][0-9][0-9]";
Regex r = new Regex(sRegex);
MyClass c = new MyClass();
// Assign the replace method to the MatchEvaluator delegate.
MatchEvaluator myEvaluator = new MatchEvaluator(c.ReplaceNums);
// Replace matched characters using the delegate method.
sInput = r.Replace(sInput, myEvaluator);
// Write out the modified string.
Console.WriteLine(sInput);
}
public string ReplaceNums(Match m)
// Replace each Regex match with match + " "
{
return m.ToString()+" ";
}
}
How's that?
It's been ages since I used C# and I can't test, but this may work as a one-liner which may be "neater" if you only need it once:
sInput = Regex("[0-9][0-9][0-9]").Replace(sInput,MatchEvaluator(Match m => m.ToString()+" "));
There is no way to do what you want unless you parse the string first.
Based on your comments, you only really need a simple formatting so you are better off just implementing a small helper method and thats it. (IMHO it's not really a good idea to parse the string if it isn't logically a number; you can't really be sure that in the future the input string might not be a number at all.
I'd go for something similar to:
public static string Group(this string s, int groupSize = 3, char groupSeparator = ' ')
{
var formattedIdentifierBuilder = new StringBuilder();
for (int i = 0; i < s.Length; i++)
{
if (i != 0 && (s.Length - i) % groupSize == 0)
{
formattedIdentifierBuilder.Append(groupSeparator);
}
formattedIdentifierBuilder.Append(s[i]);
}
return formattedIdentifierBuilder.ToString();
}
EDIT: Generalized to generic grouping size and group separator.
The problem is that # is a Digit placeholder and it is specific to numeric formatting only. Hence, you can't use this on strings.
Either parse the string to a numeric, so the formatting rules apply, or use other methods to split the string in two.
string.Format("{0:### ###}", int.Parse("123456"));

Format placeholder in string.format to pick substring of an argument

Is there a format string for the C# string.Format method that picks a substring from the corresponding argument? Like so:
var lang1 = "EN";
var lang2 = "FR";
var shortFormat = "Foo-{0:0-0}.pdf";
var longFormat = "Foo-{0:0-1}.pdf";
string.Format(shortFormat, lang1) // Foo-E.pdf
string.Format(shortFormat, lang2) // Foo-F.pdf
string.Format(longFormat, lang1) // Foo-EN.pdf
string.Format(longFormat, lang2) // Foo-FR.pdf
To anticipate a few comments: Yes, I know the Substring method. I have also read that string.Format is slower than a simple Substring. The example above is heavily simplified. Imagine that the string.Format statement resides in one place, while the lang1/lang2 argument is an input from another place and the shortFormat/longFormat is defined in a resx file.
That is, in the place where the format is to be defined we don't know anything about the value being formatted (lang1/lang2 in the example) nor do we have any means to execute C# code. Hence we can't call any method such as Substring on the value. At the place where the formatting code runs, in turn, we take the format as a parameter, so we can't simply perform a Substring on the value because we don't know whether the format requires it or not (except if we inspect the format).
No, the string.Format does not have this feature, which is better explained here: Can maximum number of characters be defined in C# format strings like in C printf?
If you don't want to use Substring I would create an extension class for string like this: http://msdn.microsoft.com/en-us/library/bb311042.aspx
namespace CustomExtensions
{
public static class StringExtension
{
public static string ShortFormat(this string str)
{
// manipulate and return str here
}
public static string LongFormat(this string str)
{
// manipulate and return str here
}
}
}
XSLT formatting can be an option: user gets ability to provide almost everything in configuration file and even execute custom c# code in your domain if it is required.
Please also consider that changes of format can be restricted to relatively small amount of actions: crop, pad or insert one or two things in some positions. Each one can be set as individual function and provided with own parameters.
There are two ways to provide custom formatting. You can either implement IFormattable on a custom type to control how that type is always formatted, or implement IFormatProvider to override how other types are formatted in specific cases.
In your case I would suggest creating a new type to encapsulate how your software deals with language codes;
public struct LanguageCode : IFormattable {
public readonly string Code;
public LanguageCode(string code) {
Code = code;
}
public override string ToString()
=> this.ToString("L", CultureInfo.CurrentCulture);
public string ToString(string format)
=> this.ToString(format, CultureInfo.CurrentCulture);
public string ToString(string format, IFormatProvider provider){
if (String.IsNullOrEmpty(format))
format = "L";
if (provider == null)
provider = CultureInfo.CurrentCulture;
switch (format.ToUpperInvariant()){
case "L": // Long
return Code.ToString(provider);
case "S": // Short
return Code.SubString(0,1).ToString(provider);
default:
throw new FormatException($"The {format} format string is not supported.");
}
}
public static implicit operator LanguageCode(string code)
=> new LanguageCode(code);
public static implicit operator string(LanguageCode language)
=> language.Code;
}
Then from your example;
var lang1 = (LanguageCode)"EN";
LanguageCode lang2 = "FR";
var shortFormat = "Foo-{0:S}.pdf";
var longFormat = "Foo-{0:L}.pdf";

Default number format for ToString

Is it possible to define a default number format that is used whenever I convert an integer (or double etc.) to a String without specifying a format string?
C# example:
int i = 123456;
string s = "Hello " + i;
// or alternatively with string.Format without format definition
string s = string.Format("Hello {0}", i);
ASP.NET Razor example:
<div>
Hello #i
</div>
I think all these code lines implicitly use the default ToString() method for Int32. And not surprisingly, all these code lines result in "Hello 123456", but I want "Hello 123,456".
So can I specify that "N0" should be used by default (at least for integer)?
I already found the question Set Default DateTime Format c# - it looked good, but it doesn't help me for numbers.
Edit: I'm aware that I could write an extension method which I can use throughout my application, but this is not what I'm looking for. I would like to find a property (maybe somewhere hidden in CultureInfo or NumberFormatInfo) which is currently set to "G" and is used by the default Int32.ToString() implementation.
If you create your own CultureInfo and you can alter it and then assign it to CultureInfo.CurrentCulture like in this answer:
https://stackoverflow.com/a/24785761/166921
You Can override systems toString() method into your class as under:
public override string ToString()
{
int i = 123456;
string s = "Hello " + i;
return string.Format("Hello {0}", i);
}
you can use extension methods
public static class MyExtensions
{
public static string ToDefaultFormatString(this int i)
{
//Staf
}
}
and your code look like
int i = 123456;
string s = "Hello " + i.ToDefaultFormatString();
As you are trying to modify the functionality for a primitive type, which has no class, you cannot override the ToString() method.
You can however create an extension method.
namespace System
{
public class IntExt
{
public string ToStringN0(this int i)
{
return i.ToString("N0");
}
}
}
and then use by
int i = 5000;
Console.WriteLine(i.ToStringN0());
The example puts the class in the System namespace so it will be available through the application.
This maybe help you :
Decimal.ToString Method (String) MSDN
Double.ToString Method (String) MSDN
asp.net mvc set number format default decimal thousands separators

C# 2.0 function which will return the formatted string

I am using C# 2.0 and I have got below type of strings:
string id = "tcm:481-191820"; or "tcm:481-191820-32"; or "tcm:481-191820-8"; or "tcm:481-191820-128";
The last part of string doesn't matter i.e. (-32,-8,-128), whatever the string is it will render below result.
Now, I need to write one function which will take above string as input. something like below and will output as "tcm:0-481-1"
public static string GetPublicationID(string id)
{
//this function will return as below output
return "tcm:0-481-1"
}
Please suggest!!
If final "-1" is static you could use:
public static string GetPublicationID(string id)
{
int a = 1 + id.IndexOf(':');
string first = id.Substring(0, a);
string second = id.Substring(a, id.IndexOf('-') - a);
return String.Format("{0}0-{1}-1", first, second);
}
or if "-1" is first part of next token, try this
public static string GetPublicationID(string id)
{
int a = 1 + id.IndexOf(':');
string first = id.Substring(0, a);
string second = id.Substring(a, id.IndexOf('-') - a + 2);
return String.Format("{0}0-{1}", first, second);
}
This syntax works even for different length patterns, assuming that your string is
first_part:second_part-anything_else
All you need is:
string.Format("{0}0-{1}", id.Substring(0,4), id.Substring(4,5));
This just uses substring to get the first four characters and then the next five and put them into the format with the 0- in there.
This does assume that your format is a fixed number of characters in each position (which it is in your example). If the string might be abcd:4812... then you will have to modify it slightly to pick up the right length of strings. See Marco's answer for that technique. I'd advise using his if you need the variable length and mine if the lengths stay the same.
Also as an additional note your original function of returning a static string does work for all of those examples you provided. I have assumed there are other numbers visible but if it is only the suffix that changes then you could happily use a static string (at which point declaring a constant or something rather than using a method would probably work better).
Obligatory Regular Expression Answer:
using System.Text.RegularExpressions;
public static string GetPublicationID(string id)
{
Match m = RegEx.Match(#"tcm:([\d]+-[\d]{1})", id);
if(m.Success)
return string.Format("tcm:0-{0}", m.Groups[1].Captures[0].Value.ToString());
else
return string.Empty;
}
Regex regxMatch = new Regex("(?<prefix>tcm:)(?<id>\\d+-\\d)(?<suffix>.)*",RegexOptions.Singleline|RegexOptions.Compiled);
string regxReplace = "${prefix}0-${id}";
string GetPublicationID(string input) {
return regxMatch.Replace(input, regxReplace);
}
string test = "tcm:481-191820-128";
stirng result = GetPublicationID(test);
//result: tcm:0-481-1

Categories

Resources