Reputation: 3527
I need help to develop a logic to split a string, but only based on the last 2 delimiters of the string.
Example inputs:
string s1 = "Dog \ Cat \ Bird \ Cow";
string s2 = "Hello \ World \ How \ Are \ You";
string s3 = "I \ am \ Peter";
Expected Outputs:
string[] newS1 = "Dog Cat", "Bird", "Cow"
string[] newS2 = "Hello World How", "Are", "You"
string[] newS3 = "I", "am", "Peter"
So, as you can see, I only want to split the string on the last 2 "\", and everything else before the last 2 "\" will be concatenated into one string.
I tried the .Split method but it will just split every "\" in a string.
Edited: If the string has less than 2 "\", it will just split according to whatever it has
Updates: Wow, these are a bunch of interesting solutions! Thank you a lot!
Upvotes: 3
Views: 193
Reputation: 149040
Offering a regex solution:
var output = Regex.Split(input, @"\s*\\\s*([^\\]*?)\s*\\\s*(?=[^\\]*$)");
This split finds the second to last element and splits around that, but captures it in a group so it will be included in the output array.
For input "Dog \ Cat \ Bird \ Cow"
, this will produce { "Dog \ Cat", "Bird", "Cow" }
. If you also need to strip the \
out of the first element that can be done with a simple replace:
output[0] = output[0].Replace(" \\", "");
Update: This version will correctly handle strings with only one delimiter:
var output = Regex.Split(str, @"\s*\\\s*([^\\]*?)\s*\\\s*(?=[^\\]*$)|(?<=^[^\\\s]*)\s*\\\s*(?=[^\\\s]*$)");
Update: And to match other delimiters like whitespace, "~"
, and "%"
, you can use a character class:
var output = Regex.Split(str, @"(?:[%~\s\\]+([^%~\s\\]+?)[%~\s\\]+|(?<=^[^%~\s\\]+)[%~\s\\]+)(?=[^%~\s\\]+$)");
The structure of this regex is slightly simpler than the previous one since it represents any sequence of one or more characters in the class [%~\s\\]
as a delimiter, and any sequence of one or more characters in the negated character class [^%~\s\\]
to be a segment. Note that the \s
means 'whitespace' character.
You might also be able to simplify this further using:
var output = Regex.Split(str, @"(?:\W+(\w+)\W+|(?<=^\w+)\W+)(?=\w+$)");
Where \w
matches any 'word' character (letters, digits, or underscores) and \W
matches any 'non-word' character.
Upvotes: 5
Reputation: 10773
Try this:
var parts = s1.Split(new[] { " \\ " }, StringSplitOptions.None);
var partsCount = parts.Count();
var result = new[] { string.Join(" ", parts.Take(partsCount - 2)) }.Concat(parts.Skip(partsCount - 2));
Upvotes: 5
Reputation: 2725
Interesting question. My initial solution to this would be:
String[] tokens = theString.Split("\\");
String[] components = new String[3];
for(int i = 0; i < tokens.length - 2; i++)
{
components[0] += tokens[i];
}
components[1] = tokens[tokens.length - 2];
components[2] = tokens[tokens.length - 1];
Upvotes: 1
Reputation: 50336
Looks like you want to Split
the string on every <space>\<space>
:
string input = @"Dog \ Cat \ Bird \ Cow";
string[] parts = input.Split(new string[]{@" \ "},
StringSplitOptions.None);
And then Join
everything with a space in between, except the final two parts:
// NOTE: Check that there are at least 2 parts.
string part0 = String.Join(" ", parts.Take(parts.Length - 2));
string part1 = parts[parts.Length - 2];
string part2 = parts[parts.Length - 1];
This will give you three strings, which you can put in an array.
string[] newParts = new []{ part0, part1, part2 };
In this example:
new [] { "Dog Cat", "Bird", "Cow" }
Upvotes: 2
Reputation: 733
Loop from the end of the string and count delimiters until you encounter two. Record index positions in 2 variables previously set to -1.
After the loop, if first var is -1, nothing happens, return whole string.
If second var is -1, create array of 2 strings, split using substring and return.
Create array of 3 string, split using information from two vars, return.
Hope you understood my pseudocode, give me a comment if you need help.
Upvotes: -1
Reputation: 4860
How about simply taking the output of split, then taking first N-2 items and Join back together, then create new string array of 3 items, first being output of Join, second being item N-1 of first split, and third being N of first split. I think that'll accomplish what you're trying to do.
Upvotes: 1