Reputation: 32160
Is there an easy way to zip 2 arrays in random locations and keep their original order?
for example
a=[0,1,2,3,4,5,6,7,8,9,10]
b=["one","two","three","four"]
and a random number from 0 to 5 with rand(5)
zipped = [0,"one",1,2,3,"two",4,"three",5,6,7,8,"four",9,10]
and the random series would be 1,3,1,4
as location to where to "zip" each element of b into a
The best I could do is
i=0
merged=a
b.each do |x|
rnd = rand(5)
merged.insert(i+rnd,x)
i=i+rnd
end
Upvotes: 4
Views: 325
Reputation: 20398
Here's a variant of Mark Hubbart's approach in a more functional style.
MergeTuple = Struct.new :place, :value
def ordered_random_merge( merge_to, merge_from )
merge_from.
map { |e| MergeTuple[ rand( merge_to.size+1 ), e ] }.
sort_by { |mt| - mt.place }.
each_with_object( merge_to.dup ) { |mt, merged| merged.insert(mt.place, mt.value) }
end
Upvotes: 0
Reputation: 3693
This version will give a balanced shuffling, with insertions not biased to either end of the array.
def ordered_random_merge(a,b)
a, b = a.dup, b.dup
a.map{rand(b.size+1)}.sort.reverse.each do |index|
b.insert(index, a.pop)
end
b
end
Upvotes: 4