-1

I'd like to interleave two arrays without exactly alternating them. For example, given:

a = [1,2,3,4,5,6,7,8,9]
b = ['a','b','c']

I'd like to receive f = [1,2,'a',3,4,'b',5,6,'c',7,8,9] as the output. I want one element from b for every two elements in a.

A solution appears to be:

a = [1,2,3,4,5,6,7,8,9]
b = ['a','b','c']

even, odd = a.partition.each_with_index{ |_, i| i.even? }
res = even.zip(odd,b)
res = res.flatten.reject(&:blank?)
#=> [1, 2, "a", 3, 4, "b", 5, 6, "c", 7, 8, 9]

but I'm not thrilled with this solution. Any ideas?

XML Slayer
  • 1,530
  • 14
  • 31

3 Answers3

4
a.each_slice(2).zip(b).flatten
#=> [1, 2, "a", 3, 4, "b", 5, 6, "c"] 
potashin
  • 44,205
  • 11
  • 83
  • 107
Mladen Jablanović
  • 43,461
  • 10
  • 90
  • 113
  • The desired behavior when there are surplus elements in any of the arrays is not defined. So I could equally claim that it works perfectly. In any case, don't you think a downvote is a bit too harsh? :) – Mladen Jablanović Jul 08 '16 at 15:00
  • Issue elaboration may be vague, but OP's desired result and the result you've posted don't match the result that your code produces, that's for sure – so I guess the downvote is justified, no offense, by the way – potashin Jul 08 '16 at 15:01
  • @sawa: for the first case, not the second, see the post – potashin Jul 08 '16 at 15:07
  • @potashin I see. It is the OP's fault. The example in the question does not make sense. The values of `a` and `b` are different between the statement and its solution. – sawa Jul 08 '16 at 15:11
  • Adding `.reject(&:blank?)` fixes the problem. – XML Slayer Jul 08 '16 at 15:23
  • @XMLSlayer Given that you made clear that you wanted to deal with arbitrary length ratio (which I have believed from the beginning that you had in mind), why are you still sticking to the given solutions that do not work with the clarified intention, while ignoring my answer? – sawa Jul 08 '16 at 15:26
  • @XMLSlayer I believe `.compact` works equally good, and doesn't require Rails. – Mladen Jablanović Jul 08 '16 at 15:28
  • @sawa, your answer (by ruby benchmark) is by far the slowest. The answer I provided also deals with arbitrary lengths, I was just hoping for cleaner solution. @mladen's answer (with a `.reject(&:blank?)` at the end) does what I'm looking for. When there are surplus elements, I'd prefer them to simply be appended at the end. – XML Slayer Jul 08 '16 at 15:35
  • @XMLSlayer Your question is, then, not clear. Do you want a fixed ratio of 2 : 1 irrespective of the ratio of the lengths of the two arrays? – sawa Jul 08 '16 at 15:37
  • @XMLSlayer And there is no such thing as `blank?` in **Ruby**. – sawa Jul 08 '16 at 15:39
  • I would like two elements from `a`, one element from `b`. Repeat for as long as I have elements from `b`. When I run out, append the rest of `a`. – XML Slayer Jul 08 '16 at 15:39
  • @sawa I am using Rails, so `blank?` will work just fine – XML Slayer Jul 08 '16 at 15:41
  • @XMLSlayer You just changed the question to add Rails tag. – sawa Jul 08 '16 at 15:42
  • Yes I did, to clarify the question for others in the future. Thank you for your help. No need to delete your answer though, it is a very helpful solution for another use-case! – XML Slayer Jul 08 '16 at 15:49
0

You can try the following (for both examples, that you've provided):

b.zip(a.each_slice(2)).map(&:reverse).flatten
# => [1, 2, "a", 3, 4, "b", 5, 6, "c"]

Demonstration

sawa
  • 165,429
  • 45
  • 277
  • 381
potashin
  • 44,205
  • 11
  • 83
  • 107
0

This works for arrays a and b of any sizes (including b.size > a.size) and ensures that the sequences of elements from a in the merged array differ in length by at most one. The same is true for sequences from b when b.size > a.size.

def insert_em(a,b)
  b.size <= a.size ? recurse(a,b) : recurse(b,a)
end

def recurse(a,b)
  i = a.size/(b.size+1)
  b.size == 1 ? a[0,i] + b + a[i..-1] :
    [*a[0,i], b.first].concat(recurse(a[i..-1], b[1..-1]))
end

a = [1,2,3,4,5,6,7,8,9]

insert_em a, ['a']
  #=> [1, 2, 3, 4, "a", 5, 6, 7, 8, 9] 
insert_em a, ['a','b']
  #=> [1, 2, 3, "a", 4, 5, 6, "b", 7, 8, 9] 
insert_em a, ['a','b','c']
  #=> [1, 2, "a", 3, 4, "b", 5, 6, "c", 7, 8, 9] 
insert_em a, ['a','b','c','d']
  #=> [1, "a", 2, 3, "b", 4, 5, "c", 6, 7, "d", 8, 9] 
insert_em a, ['a','b','c','d','e']
  #=> [1, "a", 2, "b", 3, "c", 4, 5, "d", 6, 7, "e", 8, 9] 
insert_em a, ['a','b','c','d','e','f']
  #=> [1, "a", 2, "b", 3, "c", 4, "d", 5, "e", 6, 7, "f", 8, 9] 
insert_em a, ['a','b','c','d','e','f','g']
  #=> [1, "a", 2, "b", 3, "c", 4, "d", 5, "e", 6, "f", 7, "g", 8, 9] 
insert_em a, ['a','b','c','d','e','f','g','i']
  #=> [1, "a", 2, "b", 3, "c", 4, "d", 5, "e", 6, "f", 7, "g", 8, "i", 9] 
insert_em a, ['a','b','c','d','e','f','g','i','j']
  #=> ["a", 1, "b", 2, "c", 3, "d", 4, "e", 5, "f", 6, "g", 7, "i", 8, "j", 9] 
insert_em a, ['a','b','c','d','e','f','g','i','j','k']
  #=> ["a", 1, "b", 2, "c", 3, "d", 4, "e", 5, "f", 6, "g", 7, "i", 8, "j", 9, "k"] 
insert_em a, ['a','b','c','d','e','f','g','i','j','k','l']
  #=> ["a", 1, "b", 2, "c", 3, "d", 4, "e", 5, "f", 6, "g", 7, "i", 8, "j", 9, "k", "l"] 
Cary Swoveland
  • 106,649
  • 6
  • 63
  • 100