2017-04-19 211 views
0

給用戶兩個輸入AB(集合)和一個數字X,並且必須創建一個輸出。輸出以A的第一個值開始,然後從B取得X個單位,然後是第二個值A,並繼續如此,直到AB都已用盡。你可以假設1 < X < sizeof(B)。但是,如果AB用完,您應該循環回到短集合的開始處,並繼續,直到另一個用完。循環回來應該繼續下去,直到兩個集合都結束。如何合併兩個Ruby集合?

什麼是優雅在Ruby中如何做到這一點?我有一些破解代碼,似乎無法找到一個好方法來做到這一點。不,這不是一個家庭作業問題。我有奇怪的愛好。

這裏的行爲的一些樣本測試中,我想:

# SomeModule.copy(A, B, X) 
SomeModule.copy(%w(a1 a2 a3), %w(b1 b2 b3),  1) == %w(a1 b1 a2 b2 a3 b3)) 
SomeModule.copy(%w(a1),   %w(b1),    1) == %w(a1 b1)) 
SomeModule.copy(%w(a1),   %w(b1 b2 b3),  1) == %w(a1 b1 a1 b2 a1 b3)) 
SomeModule.copy(%w(a1 a2),  %w(b1 b2 b3 b4 b5), 2) == %w(a1 b1 b2 a2 b3 b4 a1 b5 b1)) 
SomeModule.copy(%w(a1 a2),  %w(b1 b2 b3 b4 b5), 2) == %w(a1 b1 b2 a2 b3 b4 a1 b5 b1)) 
SomeModule.copy(%w(a1 a2 a3 a4), %w(b1 b2 b3 b4 b5), 3) == %w(a1 b1 b2 b3 a2 b4 b5 b1 a3 b2 b3 b4 a4 b5 b1 b2)) 
+4

什麼是你在Ruby中嘗試的方式嗎?即使是一半的,完全沒有希望的代碼也是你在解決方案上付出努力的一個標誌,它激勵人們提供幫助。 – tadman

+0

一個簡單的例子,包括你想要的結果將是有幫助的。 –

+0

@CarySwoveland我包括帶有輸入和期望輸出的樣本測試。 –

回答

1

這裏是什麼東西,這個想法是遍歷每個陣列中,直至兩者達到其最大指數:

def custom_combine(a,b,x) 
    max_index_a = a.count - 1 
    max_index_b = b.count - 1 
    a_run_out = false 
    b_run_out = false 

    output = [] 

    a.cycle.each_with_index do |elem_a, index_a| 
    output << elem_a 
    # base on a index get x elements from b 
    x.times do |i| 
     index_b = ((index_a * x) + i) % (max_index_b + 1) 
     output << b[index_b] 
     b_run_out = true if index_b == max_index_b 
    end 
    a_run_out = true if index_a == max_index_a 
    break if a_run_out && b_run_out 
    end 

    output 
end 

a = %w(a1 a2 a3 a4) 
b = %w(b1 b2 b3 b4 b5) 
x = 3 

custom_combine(a,b,x) 
# => ["a1", "b1", "b2", "b3", "a2", "b4", "b5", "b1", "a3", "b2", "b3", "b4", "a4", "b5", "b1", "b2"] 
+0

謝謝!我已經閱讀了enumerable,我想我跳過了'cycle',或者沒有完全理解它做了什麼。這是一個很好的方式來做到這一點。 –

+0

我最終想出的東西與您在這裏的內容非常相似,將集合跟蹤邏輯拉出到一個類中。 –

1

Enumerable有一個each_slice方法,它可以讓你一次迭代一個可枚舉對象N個項目。利用它,你可以做這樣的事情:

a1 = [1, 2, 3, 4, 5, 6] 
a2 = [10, 11, 12, 20, 21, 22, 30, 31, 32, 40, 41, 42, 50, 51, 52, 60] 

a1.each_slice(1).zip(a2.each_slice(3)).flatten 

# => [1, 10, 11, 12, 2, 20, 21, 22, 3, 30, 31, 32, 4, 40, 41, 42, 5, 50, 51, 52, 6, 60] 
0

這裏是最後在上午04點半跳出了我的大腦:

class InfiniteArray 
    private 
    attr_reader :collection 
    attr_accessor :index, :wrapped_count 
    public 

    def initialize(collection) 
    @collection = collection 
    reset 
    end 

    def next 
    value = collection[index] 
    if index < collection.length - 1 
     self.index = index + 1 
    else 
     self.index = 0 
     self.wrapped_count = wrapped_count + 1 
    end 
    value 
    end 

    def wrapped? 
    wrapped_count > 0 
    end 

    def reset 
    @index = 0 
    @wrapped_count = 0 
    end 
end 

class IntervalCopier 
    private 
    attr_reader :source_collection, :destination_collection, :interval 
    public 

    def initialize(source_collection, destination_collection, interval) 
    @source_collection = InfiniteArray.new(source_collection) 
    @destination_collection = InfiniteArray.new(destination_collection) 
    @interval = interval 
    end 

    def copy 
    final = [] 
    until source_collection.wrapped? && destination_collection.wrapped? do 
     final << source_collection.next 
     interval.times { final << destination_collection.next } 
    end 
    [source_collection, destination_collection].each(&:reset) 
    final 
    end 
end 
0
def copy(array1, array2, slice_length) 
    iterations = [array1.length, 
       (array2.length.to_f/slice_length.to_f).round 
       ].max 

    result = [] 
    enum1 = array1.cycle 
    enum2 = array2.cycle 

    iterations.times do 
    result << enum1.next 
    slice_length.times { result << enum2.next } 
    end 

    result 
end 

require 'minitest/autorun' 

class TestCopy < Minitest::Test 
    def test_copy 
    assert_equal(%w(a1 b1 a2 b2 a3 b3),        copy(%w(a1 a2 a3), %w(b1 b2 b3),  1)) 
    assert_equal(%w(a1 b1),           copy(%w(a1),   %w(b1),    1)) 
    assert_equal(%w(a1 b1 a1 b2 a1 b3),        copy(%w(a1),   %w(b1 b2 b3),  1)) 
    assert_equal(%w(a1 b1 b2 a2 b3 b4 a1 b5 b1),      copy(%w(a1 a2),  %w(b1 b2 b3 b4 b5), 2)) 
    assert_equal(%w(a1 b1 b2 a2 b3 b4 a1 b5 b1),      copy(%w(a1 a2),  %w(b1 b2 b3 b4 b5), 2)) 
    assert_equal(%w(a1 b1 b2 b3 a2 b4 b5 b1 a3 b2 b3 b4 a4 b5 b1 b2), copy(%w(a1 a2 a3 a4), %w(b1 b2 b3 b4 b5), 3)) 
    end 
end