Lets say I have an array (or list) of items
A[] = [a,b,c,d,e]
If I want to print them out so each item is separated by a comma (or any other delimiter), I generally have to do this:
for(int i=0; i < A.Count; i++)
{
Console.Write(A[i]);
if (i != A.Count-1)
Console.Write(",");
}
So, my output looks like:
a,b,c,d,e
Is there a better or neater way to achieve this?
I like to use a foreach loop, but that prints a comma after the last element as well, which is undesirable.
Console.WriteLine(string.Join(",", A));
You are looking for String.Join():
var list = String.join(",", A);
String.Join Method (String, String[])
Concatenates all the elements of a string array, using the specified separator between each element.
public static string Join(
string separator,
params string[] value
)
Is there a better or neater way to achieve this? I like to use a foreach loop, but that prints a comma after the last element as well, which is undesirable.
As others have said, Join does the right thing. But here's another way to think about the problem that might help you in the future. Instead of thinking of the problem as put a comma after every element except the last element -- which you correctly note makes it difficult to work with the "foreach" loop -- think of the problem as put a comma before every element except the first element. Now it is easy to do with a foreach loop!
For about a million more ways to solve a similar problem see:
Eric Lippert's challenge "comma-quibbling", best answer?
And the original blog post:
http://blogs.msdn.com/b/ericlippert/archive/2009/04/15/comma-quibbling.aspx
Use the string.Join method, very handy.
String.Join(",", my_array)
Use:
String.Join(",", arrayOfStrings);
string separator = String.Empty;
for(int i=0; i < A.Length; i++)
{
Console.Write(seperator);
Console.Write(A[i]);
separator = ",";
}
using System;
using System.Linq;
public class Program
{
public static void Main()
{
string[] values = new string[]{"banana", "papaya", "melon"};
var result = values.Aggregate((x,y) => x + ", " + y);
Console.WriteLine(result);
}
}
Related
I breezed through the documentation for the string class and didn't see any good tools for combining an arbitrary number of strings into a single string. The best procedure I could come up with in my program is
string [] assetUrlPieces = { Server.MapPath("~/assets/"),
"organizationName/",
"categoryName/",
(Guid.NewGuid().ToString() + "/"),
(Path.GetFileNameWithoutExtension(file.FileName) + "/")
};
string assetUrl = combinedString(assetUrlPieces);
private string combinedString ( string [] pieces )
{
string alltogether = "";
foreach (string thispiece in pieces) alltogether += alltogether + thispiece;
return alltogether;
}
but that seems like too much code and too much inefficiency (from the string addition) and awkwardness.
If you want to insert a separator between values, string.Join is your friend. If you just want to concatenate the strings, then you can use string.Concat:
string assetUrl = string.Concat(assetUrlPieces);
That's marginally simpler (and possibly more efficient, but probably insignificantly) than calling string.Join with an empty separator.
As noted in comments, if you're actually building up the array at the same point in the code that you do the concatenation, and you don't need the array for anything else, just use concatenation directly:
string assetUrl = Server.MapPath("~/assets/") +
"organizationName/" +
"categoryName/" +
Guid.NewGuid() + "/" +
Path.GetFileNameWithoutExtension(file.FileName) + "/";
... or potentially use string.Format instead.
I prefer using string.Join:
var result = string.Join("", pieces);
You can read about string.Join on MSDN
You want a StringBuilder, I think.
var sb = new StringBuilder(pieces.Count());
foreach(var s in pieces) {
sb.Append(s);
}
return sb.ToString();
Update
#FiredFromAmazon.com: I think you'll want to go with the string.Concat solution offered by others for
Its sheer simplicity
Higher performance. Under the hood, it uses FillStringChecked, which does pointer copies, whereas string.Join uses StringBuilder. See http://referencesource.microsoft.com/#mscorlib/system/string.cs,1512. (Thank you to #Bas).
string.Concat is the most appropriate method for what you want.
var result = string.Concat(pieces);
Unless you want to put delimiters between the individual strings. Then you'd use string.Join
var result = string.Join(",", pieces); // comma delimited result.
A simple way to do this with a regular for loop:
(since you can use the indices, plus I like these loops better than foreach loops)
private string combinedString(string[] pieces)
{
string alltogether = "";
for (int index = 0; index <= pieces.Length - 1; index++) {
if (index != pieces.Length - 1) {
alltogether += string.Format("{0}/" pieces[index]);
}
}
return alltogether;
I am parsing a set of coordinates from an XML file. Each node will have coordinates like:
-82.5,34.1,0.000 -82.6,34.2,0.000
In the code below, the coords_raw variable is already assigned the above value and I am trying to split into array lnglatset --which does look okay.
string[] lnglatset = raw_coords.Split(' ');//will yield like [0]=-82.00,34.00,00000 // Will need to get rid of the last set of zeros
foreach (string lnglat in lnglatset)
{
Console.WriteLine(lnglat);//-82.5,34.1,0.000; looks fine
}
From the above, the final value needed would be:
coords = "-82.5 34.1, -82.6 34.2";//note the space between lng/lat
But how do remove the junk values of 0.000 from each element of the array and put a space, instead of a comma between the lng and lat values in each element? I have tried some remove() function on lnglat but that was not allowed within the foreach loop. Thanks!
You can take all parts except the last one using Take method:
var parts = raw_coords.Split(' ')
.Select(x => x.Split(','))
.Select(x => string.Join(" ", x.Take(x.Length - 1)));
var result = string.Join(",", parts);
In a single line :
String result = String.Join(" ", raw_coords.Split(' ', ',')
.Select(i => double.Parse(i))
.Where(i => i != 0).Select( i => i.ToString()));
it removes each 0.000 element and removes the space and the comma.
You can't alter the members of IEnumerable during a ForEach. Instead, you can just skip the last member when splitting the raw coordinate input.
raw_coords.split(' ').Take(2).ToArray()
Like others mentioned, you can not modify iterating variable with foreach. I learnt it the hard way and ended up using simple "for" loop instead of foreach:
for(int index=0; i<lnglatset.length-2; i++)
{
}
You can use IEnumerable.Last() extension method from System.Linq.
string lastItemOfSplit = aString.Split(new char[] {#"\"[0], "/"[0]}).Last();
I have a string that looks like this
2,"E2002084700801601390870F"
3,"E2002084700801601390870F"
1,"E2002084700801601390870F"
4,"E2002084700801601390870F"
3,"E2002084700801601390870F"
This is one whole string, you can imagine it being on one row.
And I want to split this in the way they stand right now like this
2,"E2002084700801601390870F"
I cannot change the way it is formatted. So my best bet is to split at every second quotation mark. But I haven't found any good ways to do this. I've tried this https://stackoverflow.com/a/17892392/2914876 But I only get an error about invalid arguements.
Another issue is that this project is running .NET 2.0 so most LINQ functions aren't available.
Thank you.
Try this
var regEx = new Regex(#"\d+\,"".*?""");
var lines = regex.Matches(txt).OfType<Match>().Select(m => m.Value).ToArray();
Use foreach instead of LINQ Select on .Net 2
Regex regEx = new Regex(#"\d+\,"".*?""");
foreach(Match m in regex.Matches(txt))
{
var curLine = m.Value;
}
I see three possibilities, none of them are particularly exciting.
As #dvnrrs suggests, if there's no comma where you have line-breaks, you should be in great shape. Replace ," with something novel. Replace the remaining "s with what you need. Replace the "something novel" with ," to restore them. This is probably the most solid--it solves the problem without much room for bugs.
Iterate through the string looking for the index of the next " from the previous index, and maintain a state machine to decide whether to manipulate it or not.
Split the string on "s and rejoin them in whatever way works the best for your application.
I realize regular expressions will handle this but here's a pure 2.0 way to handle as well. It's much more readable and maintainable in my humble opinion.
using System;
using System.Collections.Generic;
namespace ConsoleApplication1
{
internal class Program
{
private static void Main(string[] args)
{
const string data = #"2,""E2002084700801601390870F""3,""E2002084700801601390870F""1,""E2002084700801601390870F""4,""E2002084700801601390870F""3,""E2002084700801601390870F""";
var parsedData = ParseData(data);
foreach (var parsedDatum in parsedData)
{
Console.WriteLine(parsedDatum);
}
Console.ReadLine();
}
private static IEnumerable<string> ParseData(string data)
{
var results = new List<string>();
var split = data.Split(new [] {'"'}, StringSplitOptions.RemoveEmptyEntries);
if (split.Length % 2 != 0)
{
throw new Exception("Data Formatting Error");
}
for (var index = 0; index < split.Length / 2; index += 2)
{
results.Add(string.Format(#"""{0}""{1}""", split[index], split[index + 1]));
}
return results;
}
}
}
So, I wanna know how to write the entire content of an array to a textbox by using a foreach loop in C#. My code currently looks like this:
I generate a series of random numbers which are stored in the array:
int[] iData;
Now I want to write the stored data in this array to a textbox by using the foreach loop like this:
foreach (int myInt in iData)
{
txtListing.Text = myInt.ToString();
}
This will only write the last generated number in the array to the textbox, but my question is how do I write all of them to the tekstbox.
I only know, how to do this with a listbox and a forLoop. But is there any way this can be done with a textbox and a foreach loop?
Try using the AppendText method instead:
foreach (int myInt in iData)
{
txtListing.AppendText(myInt.ToString());
}
Another option is to join the elements together as a string:
textListing.Text = string.Join(string.Empty, iData);
...or if you want another delimiter:
textListing.Text = string.Join(", ", iData);
You need to append the strings successively.
foreach (int myInt in iData)
{
txtListing.Text += myInt.ToString();
}
The low tech approach:
foreach (int myInt in iData)
{
txtListing.Text = txtListing.Text + "; " + myInt.ToString();
}
This is writing the content of each item in turn to the text property, which is leaving the last entry in place as there's no further changes.
You're probably best off using String.Join to concatenate all the values together and write to the Text property.
i.e.
String.Join(", ", iData.Select(x => x.ToString()));
As Fredrik pointed out,
String.Join(", ", iData);
Is neater.
Try:
foreach (int myInt in iData)
{
txtListing.Text += myInt.ToString();
}
This should append each value to the .Text property, rather than overwrite it.
1) Set
txtListting.MultiLine = true
2) Change code:
txtListing.Text += myInt.ToString() + "\n";
First remove null values of the array using linq:
Array = Array.where(x => !string.isNullOrEmpty(x)).ToArray();
Convert to string:
String result = string.join("",Array);
Write to textbox:
Textbox.text=result.tostring();
DidnĀ“t use foreach but may solve your problem
I have a block of text and I want to get its lines without losing the \r and \n at the end. Right now, I have the following (suboptimal code):
string[] lines = tbIn.Text.Split('\n')
.Select(t => t.Replace("\r", "\r\n")).ToArray();
So I'm wondering - is there a better way to do it?
Accepted answer
string[] lines = Regex.Split(tbIn.Text, #"(?<=\r\n)(?!$)");
The following seems to do the job:
string[] lines = Regex.Split(tbIn.Text, #"(?<=\r\n)(?!$)");
(?<=\r\n) uses 'positive lookbehind' to match after \r\n without consuming it.
(?!$) uses negative lookahead to prevent matching at the end of the input and so avoids a final line that is just an empty string.
Something along the lines of using this regular expression:
[^\n\r]*\r\n
Then use Regex.Matches().
The problem is you need Group(1) out of each match and create your string list from that. In Python you'd just use the map() function. Not sure the best way to do it in .NET, you take it from there ;-)
Dmitri, your solution is actually pretty compact and straightforward. The only thing more efficient would be to keep the string-splitting characters in the generated array, but the APIs simply don't allow for that. As a result, every solution will require iterating over the array and performing some kind of modification (which in C# means allocating new strings every time). I think the best you can hope for is to not re-create the array:
string[] lines = tbIn.Text.Split('\n');
for (int i = 0; i < lines.Length; ++i)
{
lines[i] = lines[i].Replace("\r", "\r\n");
}
... but as you can see that looks a lot more cumbersome! If performance matters, this may be a bit better. If it really matters, you should consider manually parsing the string by using IndexOf() to find the '\r's one at a time, and then create the array yourself. This is significantly more code, though, and probably not necessary.
One of the side effects of both your solution and this one is that you won't get a terminating "\r\n" on the last line if there wasn't one already there in the TextBox. Is this what you expect? What about blank lines... do you expect them to show up in 'lines'?
If you are just going to replace the newline (\n) then do something like this:
string[] lines = tbIn.Text.Split('\n')
.Select(t => t + "\r\n").ToArray();
Edit: Regex.Replace allows you to split on a string.
string[] lines = Regex.Split(tbIn.Text, "\r\n")
.Select(t => t + "\r\n").ToArray();
As always, extension method goodies :)
public static class StringExtensions
{
public static IEnumerable<string> SplitAndKeep(this string s, string seperator)
{
string[] obj = s.Split(new string[] { seperator }, StringSplitOptions.None);
for (int i = 0; i < obj.Length; i++)
{
string result = i == obj.Length - 1 ? obj[i] : obj[i] + seperator;
yield return result;
}
}
}
usage:
string text = "One,Two,Three,Four";
foreach (var s in text.SplitAndKeep(","))
{
Console.WriteLine(s);
}
Output:
One,
Two,
Three,
Four
You can achieve this with a regular expression. Here's an extension method with it:
public static string[] SplitAndKeepDelimiter(this string input, string delimiter)
{
MatchCollection matches = Regex.Matches(input, #"[^" + delimiter + "]+(" + delimiter + "|$)", RegexOptions.Multiline);
string[] result = new string[matches.Count];
for (int i = 0; i < matches.Count ; i++)
{
result[i] = matches[i].Value;
}
return result;
}
I'm not sure if this is a better solution. Yours is very compact and simple.