Mejor forma para la concatenación especial de dos strings

Quiero concatenar dos strings de tal manera que, después del primer carácter de la primera string, llegue el primer carácter de la segunda string, y luego llegue el segundo carácter de la primera string y luego llegue el segundo carácter de la segunda string y así en. Mejor explicado por algunos ejemplos de casos:

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

Si:

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

Si:

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

He escrito el siguiente código que da el resultado esperado, pero parece que hay un montón de código. ¿Hay alguna forma más eficiente de hacer esto?

 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); } } 

También escribí la misma lógica en Javascript, que funciona bien, pero de nuevo, un montón de código.

 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); 
 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(); 

En JavaScript, al trabajar con cadenas, también está trabajando con matrices, por lo que será más fácil. También + se concatenará para ti. Reemplace la indexing de cadenas con charAt si quiere IE7-support.

Aquí está el violín:

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); 
 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; } 

Posiblemente se podría mejorar a través de un generador de strings

Solo por el bien de la curiosidad, aquí hay un trazador de líneas ilegible (que, sin embargo, he dividido en varias líneas;))

Esto utiliza el hecho de que rellenar una cadena con una cierta longitud no hace nada si la cadena ya tiene al less esa longitud. Eso significa que acolchonar cada string a la longitud de la otra string tendrá el resultado de rellenar con espacios el más corto a la longitud del más largo.

Luego usamos .Zip() para concatenar cada uno de los pares de caracteres en una cadena.

Luego llamamos a string.Concat(IEnumerable<string>) para concatenar las cadenas comprimidas en una sola cadena.

Finalmente, eliminamos los espacios de relleno adicionales que introdujimos anteriormente utilizando string.Replace() .

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

En una línea [inserta el ícono de Horror codificado aquí]:

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

Justo fuera de mi cabeza, así es como podría hacerlo.

  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++; } 

Aquí hay otro delineador:

 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)); 

Básicamente, esto convierte ambas cadenas en dictionarys con keys que harán que la cadena resultante se ordere correctamente. El range Enumerable se usa para asociar un índice con cada letra de la cadena. Cuando almacenamos los dictionarys, multiplica el índice en s1 por 2, lo que resulta en <0, M>, <2, a>, <4, r>, <6, k>, y multiplica s2 por 2 y luego agrega 1, resultando en <1, Z>, <3, u>, <5, k>, etc.

Una vez que tenemos estos dictionarys, los combinamos con .Concat y los orderamos con .OrderBy, que nos da <0, M>, <1, Z>, <2, a>, <3, u>, .. Luego, los volcamos en la string final con la string. Únete al principio.

Ok, esta es la * segunda solución más corta que pude encontrar:

  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"); 

¡Ups! Mi original más corto fue el mismo que el de la marca de arriba … ¡así que el segundo más corto que pude encontrar! Esperaba poder recortarlo con la recursión, pero no tanto.