Appending a string in a loop in effective way - c#

for long time , I always append a string in the following way.
for example if i want to get all the employee names separated by some symbol , in the below example i opeted for pipe symbol.
string final=string.Empty;
foreach(Employee emp in EmployeeList)
{
final+=emp.Name+"|"; // if i want to separate them by pipe symbol
}
at the end i do a substring and remove the last pipe symbol as it is not required
final=final.Substring(0,final.length-1);
Is there any effective way of doing this.
I don't want to appened the pipe symbol for the last item and do a substring again.

Use string.Join() and a Linq projection with Select() instead:
finalString = string.Join("|", EmployeeList.Select( x=> x.Name));
Three reasons why this approach is better:
It is much more concise and readable
– it expresses intend, not how you
want to achieve your goal (in your
case concatenating strings in a
loop). Using a simple projection with Linq also helps here.
It is optimized by the framework for
performance: In most cases string.Join() will
use a StringBuilder internally, so
you are not creating multiple strings that are
then un-referenced and must be
garbage collected. Also see: Do not
concatenate strings inside loops
You don’t have to worry about special cases. string.Join()
automatically handles the case of
the “last item” after which you do
not want another separator, again
this simplifies your code and makes
it less error prone.

I like using the aggregate function in linq, such as:
string[] words = { "one", "two", "three" };
var res = words.Aggregate((current, next) => current + ", " + next);

You should join your strings.
Example (borrowed from MSDN):
using System;
class Sample {
public static void Main() {
String[] val = {"apple", "orange", "grape", "pear"};
String sep = ", ";
String result;
Console.WriteLine("sep = '{0}'", sep);
Console.WriteLine("val[] = {{'{0}' '{1}' '{2}' '{3}'}}", val[0], val[1], val[2], val[3]);
result = String.Join(sep, val, 1, 2);
Console.WriteLine("String.Join(sep, val, 1, 2) = '{0}'", result);
}
}

For building up like this, a StringBuilder is probably a better choice.

For your final pipe issue, simply leave the last append outside of the loop
int size = EmployeeList.length()
for(int i = 0; i < size - 1; i++)
{
final+=EmployeeList.getEmployee(i).Name+"|";
}
final+=EmployeeList.getEmployee(size-1).Name;

Related

Multiple string.Replace - avoid replacing twice [duplicate]

This question already has answers here:
Replace Multiple String Elements in C#
(10 answers)
Closed 5 years ago.
My code uses String.Replace several times in a row:
mystring = mystring.Replace("somestring", variable1);
mystring = mystring.Replace("somestring2", variable2);
mystring = mystring.Replace("somestring3", variable1);
I suspect there's a better and faster way to do it. What would you suggest?
For an 'easy' alternative just use a StringBuilder....
StringBuilder sb = new StringBuilder("11223344");
string myString =
sb
.Replace("1", string.Empty)
.Replace("2", string.Empty)
.Replace("3", string.Empty)
.ToString();
Are we going for ways to make this harder to understand what is going on?
If so regex is your friend
var replacements = new Dictionary<string,string>()
{
{"somestring",someVariable1},
{"anotherstring",someVariable2}
};
var regex = new Regex(String.Join("|",replacements.Keys.Select(k => Regex.Escape(k))));
var replaced = regex.Replace(input,m => replacements[m.Value]);
Live: http://rextester.com/SXXB8348
You could at least chain the statements:
mystring = mystring.Replace("somestring", variable1)
.Replace("somestring2", variable2)
.Replace("somestring3", variable3);
Calling Replace three times is not only a valid answer, it might be the preferred one:
RegEx takes three steps: Parse, Execute, Formulate. But String.Replace is hard-coded, so in many cases it has superior speed. And a complex RegEx isn't as readable as a well-formatted chain of Replace statements. (Compare Jonathan's solution to Daniel's)
If you're still not convinced that Replace is better for your case, make a competition out of it! Try both methods side-by-side and use a Stopwatch to see how many milliseconds you save when using your data.
But DON'T optimize prematurely! Any developer will prefer readability and maintainability over a cryptic pile of spaghetti that performs three milliseconds faster.
This article Regex: replace multiple strings in a single pass with C# can be helpful:
static string MultipleReplace(string text, Dictionary replacements) {
return Regex.Replace(text,
"(" + String.Join("|", adict.Keys.ToArray()) + ")",
delegate(Match m) { return replacements[m.Value]; }
);
}
// somewhere else in code
string temp = "Jonathan Smith is a developer";
adict.Add("Jonathan", "David");
adict.Add("Smith", "Seruyange");
string rep = MultipleReplace(temp, adict);
Depending how your data is organized (what you're replacing) or how many you have; an array and loops might be a good approach.
string[] replaceThese = {"1", "2", "3"};
string data = "replace1allthe2numbers3";
foreach (string curr in replaceThese)
{
data = data.Replace(curr, string.Empty);
}
If you don't want to use RegEx add this class to your project,
It uses an extension method 'MultipleReplace':
public static class StringExtender
{
public static string MultipleReplace(this string text, Dictionary<string, string> replacements)
{
string retVal = text;
foreach (string textToReplace in replacements.Keys)
{
retVal = retVal.Replace(textToReplace, replacements[textToReplace]);
}
return retVal;
}
}
Then you can use this piece of code:
string mystring = "foobar";
Dictionary<string, string> stringsToReplace = new Dictionary<string,string>();
stringsToReplace.Add("somestring", variable1);
stringsToReplace.Add("somestring2", variable2);
stringsToReplace.Add("somestring3", variable1);
mystring = mystring.MultipleReplace(stringsToReplace);
My preferred method is to use the power of Regex to solve a multiple replace problem. The only issue with this approach is you only get to choose one string to replace with.
The following will replace all '/' or ':' with a '-' to make a valid file name.
Regex.Replace("invalid:file/name.txt", #"[/:]", "-");

Optimize an iteration of IEnumerable<string> [duplicate]

for long time , I always append a string in the following way.
for example if i want to get all the employee names separated by some symbol , in the below example i opeted for pipe symbol.
string final=string.Empty;
foreach(Employee emp in EmployeeList)
{
final+=emp.Name+"|"; // if i want to separate them by pipe symbol
}
at the end i do a substring and remove the last pipe symbol as it is not required
final=final.Substring(0,final.length-1);
Is there any effective way of doing this.
I don't want to appened the pipe symbol for the last item and do a substring again.
Use string.Join() and a Linq projection with Select() instead:
finalString = string.Join("|", EmployeeList.Select( x=> x.Name));
Three reasons why this approach is better:
It is much more concise and readable
– it expresses intend, not how you
want to achieve your goal (in your
case concatenating strings in a
loop). Using a simple projection with Linq also helps here.
It is optimized by the framework for
performance: In most cases string.Join() will
use a StringBuilder internally, so
you are not creating multiple strings that are
then un-referenced and must be
garbage collected. Also see: Do not
concatenate strings inside loops
You don’t have to worry about special cases. string.Join()
automatically handles the case of
the “last item” after which you do
not want another separator, again
this simplifies your code and makes
it less error prone.
I like using the aggregate function in linq, such as:
string[] words = { "one", "two", "three" };
var res = words.Aggregate((current, next) => current + ", " + next);
You should join your strings.
Example (borrowed from MSDN):
using System;
class Sample {
public static void Main() {
String[] val = {"apple", "orange", "grape", "pear"};
String sep = ", ";
String result;
Console.WriteLine("sep = '{0}'", sep);
Console.WriteLine("val[] = {{'{0}' '{1}' '{2}' '{3}'}}", val[0], val[1], val[2], val[3]);
result = String.Join(sep, val, 1, 2);
Console.WriteLine("String.Join(sep, val, 1, 2) = '{0}'", result);
}
}
For building up like this, a StringBuilder is probably a better choice.
For your final pipe issue, simply leave the last append outside of the loop
int size = EmployeeList.length()
for(int i = 0; i < size - 1; i++)
{
final+=EmployeeList.getEmployee(i).Name+"|";
}
final+=EmployeeList.getEmployee(size-1).Name;

Finding longest word in string

Ok, so I know that questions LIKE this have been asked a lot on here, but I can't seem to make solutions work.
I am trying to take a string from a file and find the longest word in that string.
Simples.
I think the issue is down to whether I am calling my methods on a string[] or char[], currently stringOfWords returns a char[].
I am trying to then order by descending length and get the first value but am getting an ArgumentNullException on the OrderByDescending method.
Any input much appreciated.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
namespace TextExercises
{
class Program
{
static void Main(string[] args)
{
var fileText = File.ReadAllText(#"C:\Users\RichardsPC\Documents\TestText.txt");
var stringOfWords = fileText.ToArray();
Console.WriteLine("Text in file: " + fileText);
Console.WriteLine("Words in text: " + fileText.Split(' ').Length);
// This is where I am trying to solve the problem
var finalValue = stringOfWords.OrderByDescending(n => n.length).First();
Console.WriteLine("Largest word is: " + finalValue);
}
}
}
Don't split the string, use a Regex
If you care about performance you don't want to split the string. The reason in order to do the split method will have to traverse the entire string, create new strings for the items it finds to split and put them into an array, computational cost of more than N, then doing an order by you do another (at least) O(nLog(n)) steps.
You can use a Regex for this, which will be more efficient, because it will only iterate over the string once
var regex = new Regex(#"(\w+)\s",RegexOptions.Compiled);
var match = regex.Match(fileText);
var currentLargestString = "";
while(match.Success)
{
if(match.Groups[1].Value.Length>currentLargestString.Length)
{
currentLargestString = match.Groups[1].Value;
}
match = match.NextMatch();
}
The nice thing about this is that you don't need to break the string up all at once to do the analysis and if you need to load the file incrementally is a fairly easy change to just persist the word in an object and call it against multiple strings
If you're set on using an Array don't order by just iterate over
You don't need to do an order by your just looking for the largest item, computational complexity of order by is in most cases O(nLog(n)), iterating over the list has a complexity of O(n)
var largest = "";
foreach(var item in strArr)
{
if(item.Length>largest.Length)
largest = item;
}
Method ToArray() in this case returns char[] which is an array of individual characters. But instead you need an array of individual words. You can get it like this:
string[] stringOfWords = fileText.Split(' ');
And you have a typo in your lambda expression (uppercase L):
n => n.Length
Try this:
var fileText = File.ReadAllText(#"C:\Users\RichardsPC\Documents\TestText.txt");
var words = fileText.Split(' ')
var finalValue = fileText.OrderByDescending(n=> n.Length).First();
Console.WriteLine("Longest word: " + finalValue");
As suggested in the other answer, you need to split your string.
string[] stringOfWords = fileText.split(new Char [] {',' , ' ' });
//all is well, now let's loop over it and see which is the biggest
int biggest = 0;
int biggestIndex = 0;
for(int i=0; i<stringOfWords.length; i++) {
if(biggest < stringOfWords[i].length) {
biggest = stringOfWords[i].length;
biggestIndex = i;
}
}
return stringOfWords[i];
What we're doing here is splitting the string based on whitespace (' '), or commas- you can add an unlimited number of delimiters there - each word, then, gets its own space in the array.
From there, we're iterating over the array. If we encounter a word that's longer than the current longest word, we update it.

remove first element from array

PHP developer here working with c#.
I'm using a technique to remove a block of text from a large string by exploding the string into an array and then shifting the first element out of the array and turning what remains back into a string.
With PHP (an awesome & easy language) it was just
$array = explode('somestring',$string);
array_shift($array);
$newstring = implode(' ', $array);
and I'm done.
I get so mad at c# for not allowing me to create dynamic arrays and for not offering me default functions that can do the same thing as PHP regarding arrays. Instead of dynamic arrays I have to create lists and predefine key structures etc. But I'm new and I'm sure there are still equally graceful ways to do the same with c#.
Will someone show me a clean way to accomplish this goal with c#?
Rephrase of question: How can I remove the first element from an array using c# code.
Here is how far I've gotten, but RemoveAt throws a error while debugging so I don't believe it works:
//scoop-out feed header information
if (entry_start != "")
{
string[] parts = Regex.Split(this_string, #entry_start);
parts.RemoveAt(0);
this_string = String.Join(" ", parts);
}
I get so mad at c# for not allowing me to create dynamic arrays
You may take a look at the List<T> class. Its RemoveAt might be worth checking.
But for your particular scenario you could simply use LINQ and the Skip extension method (don't forget to add using System.Linq; to your file in order to bring it into scope):
if (entry_start != "")
{
string[] parts = Regex.Split(this_string, #entry_start).Skip(1).ToArray();
this_string = String.Join(" ", parts);
}
C# is not designed to be quick and dirty, nor it particularly specializes in text manipulation. Furthermore, the technique you use for removing some portion of a string from a beginning is crazy imho.
Why don't you just use String.Substring(int start, int length) coupled with String.IndexOf("your delimiter")?
Here is the corresponding C# code:
string input = "a,b,c,d,e";
string[] splitvals = input.Split(',');
string output = String.Join(",", splitvals, 1, splitvals.Length-1);
MessageBox.Show(output);
You can use LINQ for this:
if (entry_start != "")
this_string = String.Join(" ", Regex.Split(this_string, #entry_start).Skip(1).ToArray());
string split = ",";
string str = "asd1,asd2,asd3,asd4,asd5";
string[] ary = str.Split(new string[] { split }, StringSplitOptions.RemoveEmptyEntries);
string newstr = string.Join(split, ary, 1, ary.Count() - 1);
splits at ",". removes the first record. then combines back with ","
As stated above, you can use LINQ. Skip(int) will return an IEnumerable<string> that you can then cast back as array.
string[] myArray = new string[]{"this", "is", "an", "array"};
myArray = myArray.Skip(1).toArray();
You might be more comfortable with generic lists than arrays, which work more like PHP arrays.
List<T>
But if your goal is "to remove a block of text from a large string" then the easier way would be:
string Example = "somestring";
string BlockRemoved = Example.Substring(1);
// BlockRemoved = "omestring"
Edit
I misunderstood the question, thinking you were just removing the first element from the array where the array consisted of the characters that make up the string.
To split a string by a delimiter, look at the String.Split method instead. Some good examples are given here.

convert a string[] to string with out using foreach

string x;
foreach(var item in collection)
{
x += item+",";
}
can I write something like this with lambdas?
Assuming C#, have you tried String.Join()? Or is using lambdas mandatory?
Example:
string[] myStrings = ....;
string result = String.Join(",", myStrings);
EDIT
Although the original title (and example) was about concatenating strings with a separator (to which String.Join() does the best job in my opinion), the original poster seems to ask about the broader solution: how to apply a custom format a list of strings.
My answer to that is write your own method. String.Join has a purpose, reflected by its name (joins some strings). It's high chance that your format logic has a meaning in your project, so write it, give it a proper name and use it.
For instance, if you want to output <li>text</li> for every item, make something as this:
string FormatAsListItems(string[] myStrings)
{
StringBuilder sb = new StringBuilder();
foreach (string myString in myStrings)
{
sb.Append("<li>").Append(myString).Append("</li>");
}
}
I think the intent is clearer, and you also don't take the performance hit of concatenating strings in a loop.
string x = string.Join(",", collection);
You are looking too far for the solution. The String class has a Join method for this:
string x = String.Join(",", collection);
string[] text = new string[] { "asd", "123", "zxc", "456" };
var result = texts.Aggregate((total, str) => total + "," + str);
Shorter syntax, thanks to Earwicker
Does this answer your question?
Most efficient way to concatenate strings?
Note that you can do this with Aggregate, but the built-in string.Join is both easier to use and faster for long arrays.

Categories

Resources