2013-07-24 2 views
3

Я хочу объединить две строки таким образом, чтобы после первого символа первой строки появился первый символ второй строки, а затем появился второй символ первой строки а затем появляется второй символ второй строки и т. д. Лучший объяснить некоторые примеры случаев:Лучший способ для специальной конкатенации двух строк

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

если:

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

если:

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

Я написал следующий код, который дает ожидаемый результат, но его, кажется, много кода. Есть ли более эффективный способ сделать это?

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

Я написал ту же логику и в Javascript, который отлично работает, но снова много кода.

+0

но ......... почему – Jonesopolis

+3

@Jonesy Ничто не просто для удовольствия и некоторой практики. :) – RahulD

+1

Использование IEnumerable .Zip. Вам нужно будет добавить хвосты. – Maarten

ответ

6
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); 
+0

Большое спасибо за ответ. Я собираюсь попробовать это. :) – RahulD

+0

Работает отлично. :) +1 – RahulD

5

В JavaScript при работе со строками вы также работаете с массивами, так что это будет проще. Также + будет конкатенировать для вас. Замените индексирование строк на charAt, если вы хотите поддержку IE7.

Вот скрипка:

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

Если одна строка длиннее другой, это не будет работать. – Sayse

+2

Теперь, после ваших изменений :-) – Maarten

+0

Если это важно, старые браузеры (по крайней мере, IE 7 и выше) не поддерживают 'String [index] '- вы должны использовать' String.charAt (index) 'для лучшей поддержки – Ian

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

могло быть улучшено с помощью StringBuilder

+1

Спасибо за ответ. Я попробую это. Да, я тоже подумал о StringBuilder, но пока не применил. – RahulD

5
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(); 
+1

Спасибо за ответ. :) +1 – RahulD

+0

Приятное использование stringbuilder .. хотя я действительно верю, что у этого много чрезмерного 'if' проверки .... ie' s1 = "a", s2 = "bcderfgasdfaersasadfas" ' – Sayse

+1

Было бы немного лучше скажем, 'new StringBuilder (s1.Length + s2.Length)', иначе в процессе выполнения может понадобиться копировать следующий массив в более длинный массив. –

2

Только от верхней части головы, это как я могу это сделать Это.

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

+ 1.Просто проверено .. :) – RahulD

3

Просто ради любопытства, вот нечитаемым один вкладыш (который я все-таки разделить на несколько строк;))

При этом используется тот факт, что дополняя строку до определенной длины не делает ничего если строка уже не меньше этой длины. Это означает, что добавление каждой строки к длине другой строки будет иметь результат отладки с пробелами, более короткий, с длиной более длинной.

Затем мы используем .Zip(), чтобы объединить каждую из пар символов в строку.

Затем мы вызываем string.Concat(IEnumerable<string>), чтобы объединить застегнутые строки в одну строку.

Наконец, мы удаляем дополнительные прокладки, которые мы вводили ранее, используя string.Replace().

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

На одной строке [вставить Coding Horror значок здесь]:

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

Спасибо за объяснение, это действительно помогло. :) +1 – RahulD

2

Вот еще один лайнер:

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

В основном, это преобразует обе строки в словарях с ключами, которые будут получите полученную строку для правильного упорядочения. Диапазон Enumerable используется для связывания индекса с каждой буквой в строке. Когда мы храним словари, он умножает индекс на s1 на 2, в результате получается < 0, M>, < 2, a>, < 4, r>, < 6, k> и умножает s2 на 2, затем добавляет 1, в результате < 1, Z>, < 3, и>, < 5, к> и т.д.

После того, как у нас есть эти словари, мы сочетаем их с .Concat и сортировать их с .OrderBy, что дает нам < 0, M>, < 1, Z>, < 2, a>, < 3, u>, ... Затем мы просто сбрасываем их в финальную строку с помощью string.join в начале.

+0

Спасибо за ответ. Не могли бы вы немного объяснить, я не специалист в C#. :) – RahulD

+0

Да, не беспокойтесь. См. Edit в ответе! – MaxPRafferty

+0

Большое спасибо. +1 :) – RahulD

1

Хорошо, это * второй кратчайшее решение, которое я мог придумать:

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

Упс! Моя оригинальная кратчайшая была такой же, как и над отметкой выше ... так что, во-вторых, я мог бы придумать! Я надеялся, что смогу покончить с рекурсией, но не так много.

+0

Приветствия! +1 снова. – RahulD

Смежные вопросы