RahulD
RahulD

Reputation: 709

Better way for the special concatenation of two strings

I want to concatenate two strings in such a way, that after the first character of the first string, the first character of second string comes, and then the second character of first string comes and then the second character of the second string comes and so on. Best explained by some example cases:

    s1="Mark";
    s2="Zukerberg";  //Output=> MZaurkkerberg

if:

    s1="Zukerberg";
    s2="Mark"        //Output=> ZMuakrekrberg

if:

    s1="Zukerberg";
    s2="Zukerberg";  //Output=> ZZuukkeerrbbeerrgg

I've written the following code which gives the expected output but its seems to be a lot of code. Is there any more efficient way for doing this?

public void SpecialConcat(string s1, string s2)
        {
            string[] concatArray = new string[s1.Length + s2.Length];
            int k = 0;
            string final = string.Empty;
            string superFinal = string.Empty;
            for (int i = 0; i < s1.Length; i++)
            {
                for (int j = 0; j < s2.Length; j++)
                {
                    if (i == j)
                    {
                        concatArray[k] = s1[i].ToString() + s2[j].ToString();
                        final = string.Join("", concatArray);
                    }
                }
                k++;
            }
            if (s1.Length > s2.Length)
            {
                string subOne = s1.Remove(0, s2.Length);
                superFinal = final + subOne;
            }
            else if (s2.Length > s1.Length)
            {
                string subTwo = s2.Remove(0, s1.Length);
                superFinal = final + subTwo;
            }
            else
            {
                superFinal = final;
            }
            Response.Write(superFinal);
        }
    }

I have written the same logic in Javascript also, which works fine but again a lot of code.

Upvotes: 5

Views: 5963

Answers (10)

Francisco Neto
Francisco Neto

Reputation: 160

A simple alternative without Linq witchcraft:

string Merge(string one, string two)
{
    var buffer = new char[one.Length + two.Length];
    var length = Math.Max(one.Length, two.Length);
    var index = 0;

    for (var i = 0; i < length; i ++)
    {
        if (i < one.Length) buffer[index++] = one[i];
        if (i < two.Length) buffer[index++] = two[i];
    }

    return new string(buffer);
}

Upvotes: 0

Nara
Nara

Reputation: 155

var sWordOne = "mark";// ABCDEF
var sWordTwo = "zukerberg";// 123
var result  = (sWordOne.Length > sWordTwo.Length) ? zip(sWordOne, sWordTwo) : zip(sWordTwo, sWordOne);
//result = "zmuakrekrberg"


 static string zip(string sBiggerWord, string sSmallerWord)
{
    if (sBiggerWord.Length < sSmallerWord.Length) return string.Empty;// Invalid 
    if (sSmallerWord.Length == 0) sSmallerWord = " ";
    return string.IsNullOrEmpty(sBiggerWord) ? string.Empty : (sBiggerWord[0] + "" + sSmallerWord[0] + zip(sBiggerWord.Substring(1),sSmallerWord.Substring(1))).Replace(" ","");
}

Upvotes: 1

MaxPRafferty
MaxPRafferty

Reputation: 4977

Ok, this is the *second shortest solution I could come up with:

    public string zip(string s1, string s2)
    {
        return (string.IsNullOrWhiteSpace(s1+s2))
            ? (s1[0] + "" + s2[0] + zip(s1.Substring(1) + " ", s2.Substring(1) + " ")).Replace(" ", null)
            : "";
    }

    var result =  zip("mark","zukerberg");

Whoops! My original shortest was the same as mark's above...so, second shortest i could come up with! I had hoped I could really trim it down with the recursion, but not so much.

Upvotes: 1

MaxPRafferty
MaxPRafferty

Reputation: 4977

Here's another one-liner:

var s1 = "Mark";
var s2 = "Zukerberg";
var result = string.Join("", 
  Enumerable.Range(0, s1.Length).ToDictionary(x => x * 2, x => s1[x])
  .Concat(Enumerable.Range(0, s2.Length).ToDictionary(x => x * 2+1, x => s2[x]))
  .OrderBy(d => d.Key).Select(d => d.Value));

Basically, this converts both strings into dictionaries with keys that will get the resulting string to order itself correctly. The Enumerable range is used to associate an index with each letter in the string. When we store the dictionaries, it multiplies the index on s1 by 2, resulting in <0,M>,<2,a>,<4,r>,<6,k>, and multiplies s2 by 2 then adds 1, resulting in <1,Z>,<3,u>,<5,k>, etc.

Once we have these dictionaries, we combine them with the .Concat and sort them with the .OrderBy,which gives us <0,M>,<1,Z>,<2,a>,<3,u>,... Then we just dump them into the final string with the string.join at the beginning.

Upvotes: 2

Matthew Watson
Matthew Watson

Reputation: 109577

Just for the sake of curiosity, here's an unreadable one-liner (which I have nevertheless split over multiple lines ;))

This uses the fact that padding a string to a certain length does nothing if the string is already at least that length. That means padding each string to the length of the other string will have the result of padding out with spaces the shorter one to the length of the longer one.

Then we use .Zip() to concatenate each of the pairs of characters into a string.

Then we call string.Concat(IEnumerable<string>) to concatenate the zipped strings into a single string.

Finally, we remove the extra padding spaces we introduced earlier by using string.Replace().

var result = string.Concat
(
    s1.PadRight(s2.Length)
    .Zip
    (
        s2.PadRight(s1.Length), 
        (a,b)=>string.Concat(a,b)
    )
).Replace(" ", null);

On one line [insert Coding Horror icon here]:

var result = string.Concat(s1.PadRight(s2.Length).Zip(s2.PadRight(s1.Length), (a,b)=>string.Concat(a,b))).Replace(" ", null);

Upvotes: 3

smurf brainy
smurf brainy

Reputation: 77

In JavaScript, when working with strings, you are also working with arrays, so it will be easier. Also + will concatenate for you. Replace string indexing with charAt if you want IE7- support.

Here is the fiddle:

http://jsfiddle.net/z6XLh/1

var s1 = "Mark";
var s2 = "ZuckerFace";
var out ='';

var l = s1.length > s2.length ? s1.length : s2.length
for(var i = 0; i < l; i++) {
    if(s1[i]) {
        out += s1[i];
    }
    if(s2[i]){
        out += s2[i];
    }
}
console.log(out);

Upvotes: 5

Cereal
Cereal

Reputation: 3839

Just off the top of my head, this is how I might do it.

        var s1Length = s1.Length;
        var s2Length = s2.Length;
        var count = 0;
        var o = "";
        while (s1Length + s2Length > 0) {
            if (s1Length > 0) {
                s1Length--;
                o += s1[count];
            }
            if (s2Length > 0) {
                s2Length--;
                o += s2[count];
            }
            count++;
        }

Upvotes: 2

cuongle
cuongle

Reputation: 75306

var stringBuilder = new StringBuilder();
for (int i = 0; i < Math.Max(s1.Length, s2.Length); i++)
{
    if (i < s1.Length)
        stringBuilder.Append(s1[i]);

    if (i < s2.Length)
        stringBuilder.Append(s2[i]);
}

string result = stringBuilder.ToString();

Upvotes: 5

Sayse
Sayse

Reputation: 43300

static string Join(string a, string b)
{
   string returnVal = "";
   int length = Math.Min(a.Length, b.Length);
   for (int i = 0; i < length; i++)
      returnVal += "" + a[i] + b[i];

   if (a.Length > length)
      returnVal += a.Substring(length);
   else if(b.Length > length)
      returnVal += b.Substring(length);

   return returnVal;
}

Could possibly be improved through stringbuilder

Upvotes: 3

spender
spender

Reputation: 120470

var s1 = "Mark";
var s2 = "Zukerberg";
var common = string.Concat(s1.Zip(s2, (a, b) => new[]{a, b}).SelectMany(c => c));
var shortestLength = Math.Min(s1.Length, s2.Length);
var result = 
     common + s1.Substring(shortestLength) + s2.Substring(shortestLength);

Upvotes: 8

Related Questions