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"));
Related
I have a string aaaaabbbbbccccc I have a dictionary that has certain rules
Dictionary<string, string> rules = new Dictionary<string, string>();
rules.Add("abc", "aab");
rules.Add("ac", "ba");
rules.Add("cb", "cc");
This means if string has abc it will be replaced with aab but string doesn't have any rules that match. So, I am creating a new string out of the old string based on these rules. For instance, if I rearrange the old string to abcabcabcabcabc then rule can be applied. But I am stuck at rearranging. I tried using IndexOf and Remove functions but I didn't get the positive output. This is my code
string s;
s = "aaaaabbbbbccccc";
string newString = "";
int ia, ib, ic;
//Formulating rule 1
if (s.Contains("a") && s.Contains("b") && s.Contains("c"))
{
ia = s.IndexOf("a");
ib = s.IndexOf("b");
ic = s.IndexOf("c");
if (ia < ib && ib < ic)
{
newString += "abc";
s.Remove(ia, 1);
s.Remove(ib, 1);
s.Remove(ic, 1);
}
}
Console.WriteLine("New String " + newString);
Console.WriteLine("Old String " + s);
I am getting
New String abc
Old String aaaaabbbbbccccc //Which is wrong.
Can anyone help what I am doing wrong or is there any better way?
Your explanation does not match your code.
In your explanation, you say that aaaaabbbbbccccc does not match any rule (e.g. the "abc" rule). However, in your code, you are not checking if it contains "abc", but rather that it contain "a" and "b" and "c", not necessarily as a single chunk:
if (s.Contains("a") && s.Contains("b") && s.Contains("c"))
This is an important difference:
aaaaabbbbbccccc does not contain abc (rule does not apply)
aaaaabbbbbccccc does contain a, b and c (rule does apply)
You're contradicting yourself. Which is correct here, the code or your explanation? Does the rule check for the exact string, or does it check for all characters separately?
Awkward string manipulation.
Based on your code; I infer that you're not experienced with some very common string operations (no offense intended). Unless you contradict me, I'm going to assume that your explanation is correct and your code is not.
Checking if a string contains a substring:
As I explained previously, there is an important difference between checking is a string contains a substring:
s.Contains("abc") //1
and checking if a string contains each individual character of a substring:
s.Contains("a") && s.Contains("b") && s.Contains("c") //2
As a more practical example; does my username (Flater) contain the substring "Fertla"?
If you use the logic in //1, the answer is no.
If you use the logic in //2, the answer is yes.
Based on your explanation, you should be using //1
Replacing a string:
This means if string has abc it will be replaced with aab
There is a very simple method for this:
s.Replace("abc", "aab");
Some examples:
abcdef becomes aabdef
abcabcabc becomes aabaabaab (it replaces all occurrences)
uvwxyz becomes uvwxyz (if it doesn't occur, nothing gets replaced)
Take note of the second and third bullet point.
String.Replace() will replace all occurrences, in case the substring occurs more than once. Based on your explanation, I assume this is what you want (if it's possible for a substring to occur more than once, to begin with).
If the substring is not found, String.Replace() will give you the same output as its input. Nothing will be changed. This means that you can execute your rule on your string without needing to check if the substring exists:
If it does exist, then your value will be replaced; just like you want it to happen.
If it does not exist, then nothing will happen; which is also what you want to happen.
You can dramatically simplify your code!
Create your dictionary;
Dictionary<string, string> rules = new Dictionary<string, string>();
rules.Add("abc", "aab");
rules.Add("ac", "ba");
rules.Add("cb", "cc");
Define your string:
string s = "aaaaaaabbbbbbccccccc";
And the rest is easy enough:
foreach(var rule in rules)
{
s = s.Replace(rule.Key, rule.Value);
}
This will try to perform a replace for every rule that you've defined. If it finds rules that are applicable; then it will replace the values.
Note
This code assumes that your replace values do not collide. If you do want to avoid collisions, you will have to check if substrings of all defined rules exist (Contains()) before actually replacing a value.
I have a really hard time understanding you requierment, but here is a solution may you tell me if this is even close to what you want?
private static string WeirdArrangement (string input)
{
//string input = "aabbcc[aczç_eyvur]";
string validChars = "abc";
string pattern = "abc"; // Must be a composition of all valid char
var invalidChars = input.Where(c => !validChars.Contains(c));
var validOccurences = input.Where(c => validChars.Contains(c))
.GroupBy(c => c)
.Select(c => new { Char = c.Key, Count = c.Count() });
var minPattern = validOccurences.Min(o => o.Count);
// Build time
StringBuilder builder = new StringBuilder();
//new StringBuilder(pattern.Length * minPattern + invalidChars.Count() + leftoverCount);
// X time partern
for (int i = 0; i < minPattern; i++) builder.Append(pattern);
//Rest of the validOccurences
foreach (var charOccurency in validOccurences)
{
for (int i = minPattern; i < charOccurency.Count; i++) builder.Append(charOccurency.Char);
}
//Invalid char
foreach (var invalidChar in invalidChars)
{
builder.Append(invalidChar);
};
return builder.ToString();
}
Please be kind enough to tell me how I can add an integer to an existing record which starts with a string sequence like the following;
S0000 - S00027
Kind Regards,
Indunil Sanjeewa
Try this code:
string record = "S00009";
string recordPrefix = "S";
char paddingCharacter = '0';
string recordNoPart = record.Substring(recordPrefix.Length);
int nextRecordNo = int.Parse(recordNoPart) + 1;
string nextRecord = string.Format("{0}{1}", recordPrefix, nextRecordNo.ToString().PadLeft(record.Length - recordPrefix.Length, paddingCharacter));
#kurakura88 has already given the logic. I have just provided the hardcore c# code.
The logic is:
separate the "S00009" into "S" and "00009". Use string method Substring()
Parse "00009" into integer. Use Int.Parse or Int.TryParse
Add 1 into the integer
Print back the "S" and the integer. Use string.Concat or simply string + integer
You can use following approach
string input = #"S0000";
string pattern = #"\d+";
string format = #"0000";
int addend = 1;
string result = Regex.Replace(input, pattern,
m => (int.Parse(m.Value) + addend).ToString(format));
// result = S0001
Regular expression \d+ matches all digits.
MatchEvaluator converts matched value to integer. Then adds the addend. Then converts the value to a string using the specified format.
In the end using the Replace method replaces the previous value with the new value.
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);
So what I am trying to do is as follows :
example of a string is A4PC
I am trying to replace for example any occurance of "A" with "[A4]" so I would get and similar any occurance of "4" with "[A4]"
"[A4][A4]PC"
I tried doing a normal Replace on the string but found out I got
"[A[A4]]PC"
string badWordAllVariants =
restriction.Value.Replace("A", "[A4]").Replace("4", "[A4]")
since I have two A's in a row causing an issue.
So I was thinking it would be better rather than the replace on the string I need to do it on a character per character basis and then build up a string again.
Is there anyway in Linq or so to do something like this ?
You don't need any LINQ here - String.Replace works just fine:
string input = "AAPC";
string result = input.Replace("A", "[A4]"); // "[A4][A4]PC"
UPDATE: For your updated requirements I suggest to use regular expression replace
string input = "A4PC";
var result = Regex.Replace(input, "A|4", "[A4]"); // "[A4][A4]PC"
This works well for me:
string x = "AAPC";
string replace = x.Replace("A", "[A4]");
EDIT:
Based on the updated question, the issue is the second replacement. In order to replace multiple strings you will want to do this sequentially:
var original = "AAPC";
// add arbitrary room to allow for more new characters
StringBuilder resultString = new StringBuilder(original.Length + 10);
foreach (char currentChar in original.ToCharArray())
{
if (currentChar == 'A') resultString.Append("[A4]");
else if (currentChar == '4') resultString.Append("[A4]");
else resultString.Append(currentChar);
}
string result = resultString.ToString();
You can run this routine with any replacements you want to make (in this case the letters 'A' and '4' and it should work. If you would want to replace strings the code would be similar in structure but you would need to "look ahead" and probably use a for loop. Hopefully this helps!
By the way - you want to use a string builder here and not strings because strings are static which means space gets allocated every time you loop. (Not good!)
I think this should do the trick
string str = "AA4PC";
string result = Regex.Replace(str, #"(?<Before>[^A4]?)(?<Value>A|4)(?<After>[^A4]?)", (m) =>
{
string before = m.Groups["Before"].Value;
string after = m.Groups["After"].Value;
string value = m.Groups["Value"].Value;
if (before != "[" || after != "]")
{
return "[A4]";
}
return m.ToString();
});
It is going to replace A and 4 that hasn't been replaced yet for [A4].
I need to read a string, character by character, and build a new string as the output.
What's the best approach to do this in C#?
Use a StringBuilder? Use some writer/stream?
Note that there will be no I/O operations--this is strictly an in-memory transformation.
If the size of the string cannot be determined at compile time and it may also be relatively large, you should use a StringBuilder for concatenation as it acts like a mutable string.
var input = SomeLongString;
// may as well initialize the capacity as well
// as the length will be 1 to 1 with the unprocessed input.
var sb = new StringBuilder( input.Length );
foreach( char c in input )
{
sb.Append( Process( c ) );
}
if it's just one string you can use a collection to hold your characters and then just create the string using the constructor:
IEnumerable<char> myChars = ...;
string result = new string(myChars);
Using Linq and with the help of a method ProcessChar(char c) that transforms each character to its output value this could be just a query transformation (using the string constructor that takes an IEnumerable<char> as input):
string result = new string(sourceString.Select(c => ProcessChar(c)));
This is as efficient as using a StringBuilder (since StringBuilder is used internally in the string class to construct the string from the IEnumerable), but much more readable in my opinion.
Stringbuilder is usually a pretty good bet. I've written lots of javascript in webpages using it.
A StringBuilder is good idea for building your new string, because you can efficiently append new values to it. As for reading the characters from the input string, a StringReader would be a sufficient choice.
void Main()
{
string myLongString = "lf;kajsd;lfkjal;dfkja;lkdfja;lkdjf;alkjdfa";
var transformedTString = string.Join(string.Empty, myLongString.ToCharArray().Where(x => x != ';'));
transformedTString.Dump();
}
If you have more complicated logic you can move your validation to separate predicated method
void Main()
{
string myLongString = "lf;kajsd;lfkjal;dfkja;lkdfja;lkdjf;alkjdfa";
var transformedTString = string.Join(string.Empty, myLongString.ToCharArray().Where(MyPredicate));
transformedTString.Dump();
}
public bool MyPredicate(char c)
{
return c != ';';
}
What's the difference between read string and output string? I mean why do you have to read char by char?
I use this method for reading string
string str = "some stuff";
string newStr = ToNewString(str);
string ToNewString(string arg)
{
string r = string.Empty;
foreach (char c in arg)
r += DoWork(c);
return r;
}
char DoWorK(char arg)
{
// What do you want to do here?
}