user15582964
user15582964

Reputation: 13

Editing string in C#

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

Answers (6)

Ugur
Ugur

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

Klamsi
Klamsi

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

Burak
Burak

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

aloisdg
aloisdg

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

Matthew Watson
Matthew Watson

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

Boluc Papuccuoglu
Boluc Papuccuoglu

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

Related Questions