public string Format { get { return string.Format("{0}{1}v{1}", LastManStanding ? "FFA " : string.Empty, m_Teams.PlayersPerTeam); } }
should I rather use a StringBuilder?
I'm not really sure how wrong it's to conditionally format strings like that, rather than doing
public string Format
{
get
{
StringBuilder sb = new StringBuilder();
if(LastManStanding)
sb.Append("FFA ");
sb.Append(string.Format("{0}v{0}", m_Teams.PlayersPerTeam);
return sb.ToString();
}
}
For such small strings, what you are doing is fine.
Use StringBuilder when you are dealing with thousands of concatenations and/or string formatting.
Side note:
Instead of:
sb.Append(string.Format("{0}v{0}", m_Teams.PlayersPerTeam));
You can do:
sb.AppendFormat("{0}v{0}", m_Teams.PlayersPerTeam);
Wrong, no. Readable? Meh
A little formatting can go a long way
public string Format
{
get
{
return string.Format("{0}{1}v{1}",
LastManStanding ? "FFA " : string.Empty,
m_Teams.PlayersPerTeam);
}
}
The first version is preferred in my opinion, it clearly expresses your intention and its much more concise and easy to read then the second, lengthy one. I would format it like this though:
public string Format
{
get
{
return string.Format("{0}{1}v{1}", LastManStanding ? "FFA " : string.Empty,
m_Teams.PlayersPerTeam);
}
}
StringBuilder is preferred if you're doing edits on long string, in this case you don't need it.
Agree with everyone - for such small string it is ok. Note that your rewrite with StringBuilder is worse since you use String.Format instead of StringBuilder.AppendFormat.
In your case using single format string to create resulting string is benificial if you ever decide to start localizing your program in other laguages - it is possible to pull formatting tring from resources, but it is very hard to make code with StringBuilder to respect all possible languages.
Actually there could be another side of the story not realted to using StringBuilder or String.Format. Some people/teams prefer not to use ? : operator. Knowing why you were recommended to rewrite piece of code would help to target rewrite.
I'd separate the formatting logic for FFA and normal games:
public string Format
{
get
{
if(LastManStanding)
return string.Format("FFA {0}v{0}", m_Teams.PlayersPerTeam);
else
return string.Format("{0}v{0}", m_Teams.PlayersPerTeam);
}
}
It's much easier to read. And logically the format strings are separate too. It's quite likely that you'll change them separately, and I'm surprised you didn't. "FFA 2v2" doesn't make much sense to me.
Related
I have a simple xpath:
driver.findelement(by.xpath("//li[contains(text(), 'chain')]").click()
This code is working but its not recognize chain in uppercase, how to ignore case sensitive in this xpath?
You can use the contains and translate functions together like this:
//li[contains(translate(text(), 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), 'chain')]
Use translate, but to make it shorter, you may translate only characters you are looking for
//li[contains(translate(text(), 'CHAIN', 'chain'), 'chain')]
If you are going to use this a lot, you may even write a method for that. I'll write in Java (sorry, not familiar with C#):
public static void main(String[] args) {
String l = "//li[" + containsTextIgnoringCase("StackOverflow") + "]";
System.out.println(l);
}
public static String containsTextIgnoringCase(String s) {
return String.format("contains(translate(text(), '%s', '%s'), '%s')", s.toUpperCase(), s.toLowerCase(), s);
}
output:
//li[contains(translate(text(), 'STACKOVERFLOW', 'stackoverflow'), 'stackoverflow')]
There's some space for optimization (not sure if it costs the effort, but still): translate only unique chars, and handle quotes, if passed in string
Use the value of chain in the way that assign it to a separate string variable and then apply .ToUpper() extension on it.
string strChain = "chain";
string getUpper = strChain.ToUpper();
It will give you cain in uppercase.
You can use it directly inside driver.findelement.
Do you know another more proper way to do the same things ?
string initialTemplate = "{0}-{1}";
string template = string.Format(initialTemplate, "first", "{0}");
string answer = string.Format(template, "second");
Also the following way has actually known, but in my current case unfortunatelyI can't use that method(i think that that way more proper and the logic more clear):
string initialTemplate = "{0}-{{0}}";
string template = string.Format(initialTemplate, "first");
string answer = string.Format(template, "second");
Maybe is there another hint how to do that?
UPDATE
I'm so sorry but from yours answers I've learnt that my question wasn't enough clear. So I've added a little bit more description.
My situation:
//that template is actually placed in *.resx file
//I want storing only one template and use that in different situations
public const string InitialTemplate = "{0}-{1}";
public static string GetMessage(string one, string two)
{
return string.Format(InitialTemplate, one, two);
}
public static string GetTemplate(string one)
{
return string.Format(InitialTemplate, one, "{0}");
}
//or morew universal way
public static string GetTemplate(params object[] args)
{
return string.Format(InitialTemplate, args, "{0}");
}
static void Main(string[] args)
{
//in almost all cases in my project i need to use string.format like this
string message = GetMessage("one", "two");
//but there is another way where i have to use
//the template have already been assigned first argument
//the result must be "one-{0}"
string getTemplateWithAssignedFirstArg = GetTemplate("one");
}
Do you know more proper way for that kind of situation ?
If you are using C# 6 you can also use string interpolation.
https://msdn.microsoft.com/en-us/library/dn961160.aspx
var answer = $"{firstVar}-{secondVar}";
string initialTemplate = "{0}-{1}";
string answer = string.Format(initialTemplate, "first", "second");
Should do the trick. Or cut out the middle man with:
string answer = string.Format("{0}-{1}", "first", "second");
String.Format is a very useful convenience, but I'd be wary of using it to build format strings that you're going to use to create other format strings. Someone trying to maintain that code, figure out what's going on, and perhaps modify it will be baffled. Using String.Format that way is technically possible, and there could even be scenarios where it's useful, but it's probably just going to result in something that works but is very difficult to understand and debug.
My first suggestion would be to use a StringBuilder. Even when you're appending to the StringBuilder you can use String.Format if needed to create the individual strings.
I wonder if perhaps what you describe in the question is taking place across multiple methods (which is why you might be building your format string in steps.) If that's the case, I recommend not building the string in steps like that. Don't actually start building the string until you have all of the data that you need together, and then build the string at once.
I have seen questions related to string builder but was not able to find relevant answer.
My question is "Is it wise to use string builder here? if not how to use it wisely here".
This method is going to run 100000 times. In order to save some memory I used stringbuilder here. but the problem is .ToString() method. Anyway I will have to create a string using .ToString() method so why not initialize filename as string rather than StringBuilder.
internal bool isFileExists()
{
StringBuilder fileName = new StringBuilder(AppDomain.CurrentDomain.BaseDirectory + "Registry\\" + postalCode + ".html");
if (System.IO.File.Exists(fileName.ToString()))
{
return true;
}
else
{
return false;
}
}
All libraries method use string as a parameter not string builder why?
I think I got a lot of confusion in my concepts.
Actually you are not using string builder. You first make a string by:
AppDomain.CurrentDomain.BaseDirectory + "Registry\\" + postalCode + ".html"
And then feed it to the string builder.
To use StringBuilder correctly:
StringBuilder fileName = new StringBuilder();
fileName.Append(AppDomain.CurrentDomain.BaseDirectory);
fileName.Append("Registry\\");
fileName.Append(postalCode );
fileName.Append(".html");
If you make liners to make strings you can just make the string by:
string filenamestr = AppDomain.CurrentDomain.BaseDirectory + "Registry\\" + postalCode + ".html";
In this case you are making a filepath, so it is recommended to use:
Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Registry\\" , postalCode , ".html");
Given what your code do (check if a file exists), the real bottleneck will not be using a string or a stringbuilder but checking if the file really exists... So I would let the system do the concatenation of string and taking care of performances:
internal bool isFileExists()
{
return System.IO.File.Exists(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Registry\\" , postalCode , ".html"));
}
You are actually creating 4 strings here.
The first one is AppDomain.CurrentDomain.BaseDirectory + "Registry\\".
The second one is when you add + postalCode to that string.
The third one when you add + ".html".
The fourth one when you call fileName.ToString().
If you want to use StringBuilder, you should do it like this:
StringBuilder fileName = new StringBuilder(AppDomain.CurrentDomain.BaseDirectory);
fileName.Append("Registry\\");
fileName.Append(".html");
As Hans Kesting kindly reminded me, you are not really creating 4 strings. The compiler optimizes it to one call to String.Concat().
You could also use string.Format. It uses StringBuilder internally.
In your case:
var fileName = string.Format("{0}Registry\\{1}.html", AppDomain.CurrentDomain.BaseDirectory, postalCode);
Is String.Format as efficient as StringBuilder
IO operations (even File.Exists) is more time consuming than String creating; you can't avoid File.Exists test that's why, IMHO, the readability is that matters the most:
String formatting
No redundant if
Implementation:
internal bool isFileExists() {
return File.Exists(String.Format("{0}Registry\\{1}.html",
AppDomain.CurrentDomain.BaseDirectory,
postalCode));
}
In your case, it doesn't make sense to create first a StringBuilder and then a string.
Strings are immutable in C#, and when you need to make changes to them (Replace, Append, etc.) another string is created in the string pool.
The allocation of such has a cost, and in case of several different operations this cost add up and it becomes really expensive.
StringBuilder is an object that can internally change, and is much faster (has a smaller cost) for the upsaid operations, hence it's preferable to use it.
The point in which one is better than the others changes according to the scenario, but as a rule of thumb, if you find yourself changing over and over in the same method the same string, it might be a good idea to use a StringBuilder instead.
It looks weird isFileExists() doesn't use postalCode parameter. Is it just an example or piece of a real code?
I suggest you not to use File.Exists() thousands of times. Make a hashtset with file names and look it up instead.
I am trying the following stemming class :
static class StemmerSteps
{
public static string stepSufixremover(this string str, string suffex)
{
if (str.EndsWith(suffex))
{
................
}
return str;
}
public static string stepPrefixemover(this string str, string prefix)
{
if (str.StartsWith(prefix)
{
.....................
}
return str;
}
}
this class works with one prefix or suffix. is there any suggestion to allow a list of prefixes or suffixes to go through the class and compare against each (str). your kind action really appreciated.
Instead of creating your own class from scratch (unless this is homework) I would definitive use an existing library. This answer provides an example of code that that implements the Porter Stemming Algorithm:
https://stackoverflow.com/questions/7611455/how-to-perform-stemming-in-c
Put your suffix/prefixes in a collection (like a List<>), and loop through and apply each possible one. This collection would need to be passed into the method.
List<string> suffixes = ...;
for (suffix in suffixes)
if (str.EndsWith(suffix))
str = str.Remove(str.Length - suffix.Length, suffix.Length);
EDIT
Considering your comment:
"just want to look if the string starts-/endswith any of the passed strings"
may be something like this can fit your needs:
public static string stepSufixremover(this string str, IEnumerable<string> suffex)
{
string suf = suffex.Where(x=>str.EndsWith(x)).SingleOrDefault();
if(!string.IsNullOrEmpty(suf))
{
str = str.Remove(str.Length - suf.Length, suf.Length);
}
return str;
}
If you use this like:
"hello".stepone(new string[]{"lo","l"}).Dump();
it produces:
hel
The simplest code would involve regular expressions.
For example, this would identify some English suffixes:
'^(.*?)(ing|ly|ed|ious|ies|ive|es|s|ment)?$'
One problem is that stemming is not as accurate as lemmatization. Lematization would require POS tagging for accuracy. For example, you don't want to add an -ing suffix to dove if it's a noun.
Another problem is that some suffixes also require prefixes. For example, you must add en- to -rich- to add a -ment suffix in en-rich-ment -- unlike a root like -govern- where you can add the suffix without any prefix.
In my application, there are possibilities to format a string using the string.Format() function. I want to add the possibility to return blank when the result is zero.
As far as I can see, it is possible to do this using the code: 0.toString("0;; ");, but as i already mentioned, I need to use the string.Format() function (since it must be able to use for example the {0:P} format for percentage.
Does anyone knows how to blank a zero value using the string.Format() function?
String.Format() supports the ; section separator.
Try e.g. String.Format("{0:#%;;' '}", 0);.
My answer is a bit late, but you may want to try the following:
{0:#.##%;-#.##%;''}
why don't you do it with if else statement?
string result = String.Format(the value);
if(result=="0")
{
result=" ";
}
Or, perhaps more elegantly as an extension method on int:
public static class StringFormatters
{
public static string ToNonZeroString(this int i) => i == 0 ? "" : i.ToString();
}
and then
(1+1-2).ToNonZeroString()