Converting array of string to string with a defined separator - c#

I have the following code:
var days = new string[] { "1", "2", "3", "4" });
I need to convert days to a string as following:
string daysConverted = "'1','2','3','4'";
I tried using string.Join:
var daysConverted = string.Join("','", days);
but I am getting:
"1','2','3','4" // missing quotes at the beginning and at the end.
I can concatenate a quote at both sides but I was wondering if there is any syntax to do it in one shot.

You should wrap the strings into ' before joining them:
var result = String.Join(",", days.Select(s => "'" + s + "'"));

You have to add it at the end and beginning also because Join will only combine two strings. Having said this when combining "1" and "2" with a speaterator of ',' you get "1','2" where the seperator is just added between the two elements.
As of MSDN:
Concatenates all the elements of a string array, using the specified
separator between each element.
In the end the following solution seems to be best in terms of memory and speed because you have least number of string-concatenations (two for start and end and one for every element --> 2 + n).
var daysConverted = "'" + string.Join("','", days) + "'";

Well, speaking about minimal string concatenations, here is a solution utilizing LINQ Aggregate and StringBuilder. It's not so concise, but performs...zero concatenations.
var daysConverted = days.Aggregate(new StringBuilder(), (sb, s) =>
(sb.Length > 0 ? sb.Append(",") : sb).Append("'").Append(s).Append("'"))
.ToString();

I can concatenate a quote at both sides but I was wondering if there is any syntax to do it in one shot.
Not in an optimized way. string.Join internally uses a StringBuilder to compose the string. Cheating around string.Join would make your code less clear (for example by using tricky LINQ statements) AND slower.
In the end, the classical way that #HimBromBeere suggests is the best one.

Related

How to take a string, split it into an array and then join it back together

I have some code that will take in a string from console in [0,0,0,0] format. I then want to split it into an array but leave the [] and only take the numbers. How do i do this? This is what i have, i thought i could split it all and remove the brackets after but it doesnt seem to take the brackets and rather just leaves a null space. is there a way to split from index 1 to -1?
input = Console.ReadLine();
Char[] splitChars = {'[',',',']'};
List<string> splitString = new List<string>(input.Split(splitChars));
Console.WriteLine("[" + String.Join(",", splitString) + "]");
Console.ReadKey();
I love using LinqPad for such tasks, because you can use Console.WriteLine() to get the details of a result like so:
It becomes obvious that you have empty entries, i.e. "" at the beginning and the end. You want to remove those with the overloaded funtion that takes StringSplitOptions.RemoveEmptyEntries [MSDN]:
List<string> splitString = new List<string>(input.Split(splitChars, StringSplitOptions.RemoveEmptyEntries));
Result:

how to get the remaining contents of a split?

Suppose I have a string:
var myFilename = "342134_My_Awesome_File.zip
I would like to extract just: My_Awesome_File.zip.
I am attempting to do this with the following:
var removedPrependedTieBreaker = myFilename.Split('_').Skip(1);
However, that will yield an IEnumerable<string>.
How do we do a split on underscore, and get the rest of the contents?
You just need to use a different overload of split that takes the count:
var parts = myFilename.Split(new[] { '_' }, 2, StringSplitOptions.None);
var interestingData = parts[1];
You could recombine the remaining parts with String.Join. But maybe it would be better to avoid splitting and just take a substring:
myFilename.Substring(myFilename.IndexOf('_') + 1)
While I like Joe Sewell's answer, I just thought I'd give you another way (besides string.Join, as mentioned in the question comments) to make your own approach work:
var removedPrependedTieBreaker = myFilename.Split('_').Skip(1).Aggregate((current, next) => $"{current}_{next}");
This will take the IEnumerable<string> that you made and recompose the pieces as a string with _ as a delimiter.

How to split a string every time the character changes?

I'd like to turn a string such as abbbbcc into an array like this: [a,bbbb,cc] in C#. I have tried the regex from this Java question like so:
var test = "aabbbbcc";
var split = new Regex("(?<=(.))(?!\\1)").Split(test);
but this results in the sequence [a,a,bbbb,b,cc,c] for me. How can I achieve the same result in C#?
Here is a LINQ solution that uses Aggregate:
var input = "aabbaaabbcc";
var result = input
.Aggregate(" ", (seed, next) => seed + (seed.Last() == next ? "" : " ") + next)
.Trim()
.Split(' ');
It aggregates each character based on the last one read, then if it encounters a new character, it appends a space to the accumulating string. Then, I just split it all at the end using the normal String.Split.
Result:
["aa", "bb", "aaa", "bb", "cc"]
I don't know how to get it done with split. But this may be a good alternative:
//using System.Linq;
var test = "aabbbbcc";
var matches = Regex.Matches(test, "(.)\\1*");
var split = matches.Cast<Match>().Select(match => match.Value).ToList();
There are several things going on here that are producing the output you're seeing:
The regex combines a positive lookbehind and a negative lookahead to find the last character that matches the one preceding it but does not match the one following it.
It creates capture groups for every match, which are then fed into the Split method as delimiters. The capture groups are required by the negative lookahead, specifically the \1 identifier, which basically means "the value of the first capture group in the statement" so it can not be omitted.
Regex.Split, given a capture group or multiple capture groups to match on when identifying the splitting delimiters, will include the delimiters used for every individual Split operation.
Number 3 is why your string array is looking weird, Split will split on the last a in the string, which becomes split[0]. This is followed by the delimiter at split[1], etc...
There is no way to override this behaviour on calling Split.
Either compensation as per Gusman's answer or projecting the results of a Matches call as per Ruard's answer will get you what you want.
To be honest I don't exactly understand how that regex works, but you can "repair" the output very easily:
Regex reg = new Regex("(?<=(.))(?!\\1)", RegexOptions.Singleline);
var res = reg.Split("aaabbcddeee").Where((value, index) => index % 2 == 0 && value != "").ToArray();
Could do this easily with Linq, but I don't think it's runtime will be as good as regex.
A whole lot easier to read though.
var myString = "aaabbccccdeee";
var splits = myString.ToCharArray()
.GroupBy(chr => chr)
.Select(grp => new string(grp.Key, grp.Count()));
returns the values `['aaa', 'bb', 'cccc', 'd', 'eee']
However this won't work if you have a string like "aabbaa", you'll just get ["aaaa","bb"] as a result instead of ["aa","bb","aa"]

How to analyze strings

I am trying to take a string of numbers each separated by a space, and turn it into a list. The user inputs the string of numbers by typing a number, then a space, as needed. This goes into "myString." I want to take the string and take just the numbers, and add it to myList. The code I want to create is something like this:
for(int i = 0; i < myString.Length; i++)
{
//If its not a space, add it to the list
if (myString[i] != " ")
{
myList.Add(prices[i]);
}
}
The error however says that you cannot use the '!=' operator to the types char, and string. Makes sense, but I am having a hard time finding an alternative. Is there a more efficient way to turn a string of: "1 2 3 4 5" into a List?
This is for the google jams code challenge, as I am just practicing on old questions. The link can be found here:
https://code.google.com/codejam/contest/351101/dashboard#s=p0
Thank you for all the help guys! I'm always amazed at how helpful SO is for High School programmers like me who still really have no clue what they're doing :-)
Use Split method instead
var numbers = myString.Split().Select(x => int.Parse(x)).ToArray();
BTW,in order to represent a char constant single quotes are used in C#. So as already mentioned in the comments, " " is a string literal that contains a space not a char.You should use ' '
Two things:
First, to fix your error change your line to:
if (myString[i] != ' ') // change to single quotes.
Second, there is an easier way:
string.Split(new char[] {' '}); // this will return the array you're seeking...
myString[i] is a char, so instead of " " you should use ' ' single quotes.
You can use the String.Split method to split the string on the spaces, resulting in a list of stirngs representing the numbers.
myList = myString.Split(" ");
You need to split your string on space. You can use LINQ like:
List<int> list = myString.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)
.Select(int.Parse)
.ToList();
If you want a safer option and replace any invalid entry to -1 you can use int.TryParse like:
int temp;
List<int> list = myString.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)
.Select(r => { return int.TryParse(r, out temp) ? temp : -1; })
.ToList();

What's the best way to merge strings?

Let's say I have a foreach-loop with strings like this:
String newStr='';
String str='a b c d e';
foreach(String strChar in str.split(' ')) {
newStr+=strChar+',';
}
the result would be something like: a,b,c,d,e, but what I want is a,b,c,d,e without the last comma. I normally split the last comma out but this seems ugly and overweight. Is there any lightweight way to do this?
Additional to this question: Is there any easy solution to add an "and" to the constellation that the result is something like: a, b, c, d and e for user output?
p.s.: I know that I can use the replace-method in the example but this is not what I'm looking because in most cases you can't use it (for example when you build a sql string).
I would use string.Join:
string newStr = string.Join(",", str.Split(' '));
Alternatively, you could add the separator at the start of the body of the loop, but not on the first time round.
I'd suggest using StringBuilder if you want to keep doing this by hand though. In fact, with a StringBuilder you could just unconditionally append the separator, and then decrement the length at the end to trim that end.
You also wrote:
for example when you build a sql string
It's very rarely a good idea to build a SQL string like this. In particular, you should absolutely not use strings from user input here - use parameterized SQL instead. Building SQL is typically the domain of ORM code... in which case it's usually better to use an existing ORM than to roll your own :)
you're characterizing the problem as appending a comma after every string except the last. Consider characterizing it as prepending a comma before every string but the first. It's an easier problem.
As for your harder version there are several dozen solutions on my blog and in this question.
Eric Lippert's challenge "comma-quibbling", best answer?
string.Join may be your friend:
String str='a b c d e';
var newStr = string.Join(",", str.Split(' '));
Here's how you can do it where you have "and" before the last value.
var vals = str.Split(' ');
var ans = vals.Length == 1 ?
str :
string.Join(", ", vals.Take(vals.Length - 1))) + ", and " + vals.Last();
newStr = String.Join(",", str.split(' '));
You can use Regex and replace whitespaces with commas
string newst = Regex.Replace(input, " ", ",");
First, you should be using a StringBuilder for string manipulations of this sort. Second, it's just an if conditional on the insert.
System.Text.StringBuilder newStr = new System.Text.StringBuilder("");
string oldStr = "a b c d e";
foreach(string c in oldStr.Split(' ')) {
if (newStr.Length > 0) newStr.Append(",");
newStr.Append(c);
}

Categories

Resources