Mr H
Mr H

Reputation: 5304

How to merge 2 strings alternately in rails?

I have 2 strings:

a = "qwer"

b = "asd"

Result = "qawsedr"

Same is the length of b is greater than a. show alternate the characters.

What is the best way to do this? Should I use loop?

Upvotes: 1

Views: 841

Answers (2)

Jordan Running
Jordan Running

Reputation: 106107

Sebastián's answer gets the job done, but it's needlessly complex. Here's an alternative:

def merge_alternately(a, b)
  len = [a.size, b.size].max
  Array.new(len) {|n| [ a[n], b[n] ] }.join
end
merge_alternately("ab", "zsd")
# => "azbsd"

The first line gets the size of the longer string. The second line uses the block form of the Array constructor; it yields the indexes from 0 to len-1 to the block, resulting in an array like [["a", "z"], ["b", "s"], [nil, "d"]]. join turns it into a string, conveniently calling to_s on each item, which turns nil into "".

Here's another version that does basically the same thing, but skips the intermediate arrays:

def merge_alternately(a, b)
  len = [a.size, b.size].max
  len.times.reduce("") {|s, i| s + a[i].to_s + b[i].to_s }
end

len.times yields an Enumerator that yields the indexes from 0 to len-1. reduce starts with an empty string s and in each iteration appends the next characters from a and b (or ""nil.to_s—if a string runs out of characters).

You can see both on repl.it: https://repl.it/I6c8/1

Just for fun, here's a couple more solutions. This one works a lot like Sebastián's solution, but pads the first array of characters with nils if it's shorter than the second:

def merge_alternately(a, b)
  a, b = a.chars, b.chars
  a[b.size - 1] = nil if a.size < b.size
  a.zip(b).join
end

And it wouldn't be a Ruby answer without a little gsub:

def merge_alternately2(a, b)
  if a.size < b.size
    b.gsub(/./) { a[$`.size].to_s + $& }
  else
    a.gsub(/./) { $& + b[$`.size].to_s }
  end
end

See these two on repl.it: https://repl.it/I6c8/2

Upvotes: 0

Sebasti&#225;n Palma
Sebasti&#225;n Palma

Reputation: 33471

You can get the chars from your a and b string to work with them as arrays and then "merge" them using zip, then join them.

In the case of strings with different length, the array values must be reversed, so:

def merge_alternately(a, b)
  a = a.chars
  b = b.chars
  if a.length >= b.length
    a.zip(b)
  else
    array = b.zip(a)
    array.map{|e| e != array[-1] ? e.reverse  : e}
  end
end

p merge_alternately('abc', 'def').join
# => "adbecf"
p merge_alternately('ab', 'zsd').join
# => "azbsd"
p merge_alternately('qwer', 'asd').join
# => "qawsedr"

Upvotes: 2

Related Questions