Reputation: 13
given a string with words separated by spaces how would you go about merging two words if one of them is made by one character only ? An example should clarify:
"a bcd tttt" => "abcd tttt"
"abc d hhhh" => "abcd hhhh"
I would like to merge the single characer word with the one on the left in all cases where it is not the first word in the string, in this case i would like to merge it with the one on the right.
I am trying to loop through the string and create some logic but it turned out to be more complex than i was expecting.
Upvotes: 1
Views: 109
Reputation: 54
Expanding on Matthew's answer,
If you don't want the extra space in the output you can change the last line to;
Console.WriteLine(result.TrimStart(' '));
Upvotes: 0
Reputation: 906
Quite short with Regex.
string foo = "a bcd b tttt";
foo = Regex.Replace(foo, @"^(\w) (\w{2,})", "$1$2");
foo = Regex.Replace(foo, @"(\w{2,}) (\w)\b", "$1$2");
Be aware \w is [a-zA-Z0-9_] if you need an other definition you have to define you own character class.
Upvotes: 0
Reputation: 507
My answer would not be the best practice but it works for your second case, but still you should be clear about the letter merging rules.
public static void Main()
{
Console.WriteLine(Edit("abc d hhhh") == "abcd hhhh");
Console.WriteLine(Edit("abc d hhhh a") == "abcd hhhha");
Console.WriteLine(Edit("abc d hhhh a b") == "abcd hhhhab");
Console.WriteLine(Edit("abc d hhhh a def g") == "abcd hhhha defg");
}
public static string Edit(string str)
{
var result = string.Empty;
var split = str.Split(' ', StringSplitOptions.RemoveEmptyEntries);
for (int i = 0; i < split.Length; i++)
{
if(i == 0)
result += split[i];
else
{
if (i > 0 && split[i].Length == 1)
{
result += split[i];
}
else
{
result += $" {split[i]}";
}
}
}
return result;
}
As I have mentioned above, this does not work for your 1st case which is : Edit("a bcd")
would not generate "abcd"
.
Upvotes: 0
Reputation: 23521
if you want to do it with a plain for loop and string walking:
using System;
using System.Text;
public class Program
{
public static void Main()
{
Console.WriteLine(MergeOrphant("bcd a tttt") == "bcda tttt");
Console.WriteLine(MergeOrphant("bcd a tttt a") == "bcda tttta");
Console.WriteLine(MergeOrphant("a bcd tttt") == "abcd tttt");
Console.WriteLine(MergeOrphant("a b") == "ab");
}
private static string MergeOrphant(string source)
{
var stringBuilder = new StringBuilder();
for (var i = 0; i < source.Length; i++)
{
if (i == 1 && char.IsWhiteSpace(source[i]) && char.IsLetter(source[i - 1])) {
i++;
}
if (i > 0 && char.IsWhiteSpace(source[i]) && char.IsLetter(source[i - 1]) && char.IsLetter(source[i + 1]) && (i + 2 == source.Length || char.IsWhiteSpace(source[i + 2])) )
{
i++;
}
stringBuilder.Append(source[i]);
}
return stringBuilder.ToString();
}
}
Upvotes: 1
Reputation: 109577
One way to approach this is to first use string.Split(' ')
to get an array of words, which is easier to deal with.
Then you can loop though the words, handling single character words by concatenating them with the previous word, with special handling for the first word.
One such approach:
public static void Main()
{
string data = "abcd hhhh";
var words = data.Split(' ');
var sb = new StringBuilder();
for (int i = 0; i < words.Length; ++i)
{
var word = words[i];
if (word.Length == 1)
{
sb.Append(word);
if (i == 0 && i < words.Length - 1) // Single character first word is special case: Merge with next word.
sb.Append(words[++i]); // Note the "++i" to increment the loop counter, skipping the next word.
}
else
{
sb.Append(' ' + word);
}
}
var result = sb.ToString();
Console.WriteLine(result);
}
Note that this will concatenate multiple instances of single-letter words, so that "a b c d e" will result in "abcde" and "ab c d e fg" will result in "abcde fg". You don't actually specify what should happen in this case.
Upvotes: 1
Reputation: 2346
Try the below program's approach:
using System;
using System.Text;
public class Program
{
public static void Main()
{
var delimiter=new char[]{' '};
var stringToMerge="abc d hhhh";
var splitArray=stringToMerge.Split(delimiter);
var stringBuilder=new StringBuilder();
for(int wordIndex=0;wordIndex<splitArray.Length;wordIndex++)
{
var word=splitArray[wordIndex];
if(wordIndex!=0 && word.Length>1)
{
stringBuilder.Append(" ");
}
stringBuilder.Append(word);
}
Console.WriteLine(stringBuilder.ToString());
}
}
Basically, you split the string to words, then using StringBuilder, build a new string, inserting a space before a word only if the word is larger than one character.
Upvotes: 1