Search code examples
rubyarrayslongest-prefix

Longest common prefix and suffix of arrays


What is the best way to get the longest common prefix (sub-array that starts from index 0 of the original) and suffix (sub-array that ends with index -1 of the original) of two arrays? For example, given two arrays:

[:foo, 1, :foo, 0, nil, :bar, "baz", false]
[:foo, 1, :foo, 0, true, :bar, false]

the longest common prefix of these arrays is:

[:foo, 1, :foo, 0]

and the longest common suffix of these arrays is:

[false]

When the elements at index 0/-1 differ in the original arrays, then the common prefix/suffix should be an empty array.


Solution

  • One possible solution:

    a1 = [:foo, 1, 0, nil, :bar, "baz", false]
    a2 = [:foo, 1, 0, true, :bar, false]
    
    a1.zip(a2).take_while { |x, y| x == y }.map(&:first)
    #=> [:foo, 1, 0]
    

    Reversing the input arrays and the output array finds a common suffix:

    a1.reverse.zip(a2.reverse).take_while { |x, y| x == y }.map(&:first).reverse
    #=> [false]
    

    Edge case: zip fills "argument" arrays with nil values:

    a1 = [true, nil, nil]
    a2 = [true]
    
    a1.zip(a2).take_while { |x, y| x == y }.map(&:first)
    #=> [true, nil, nil]
    

    This can be avoided by truncating the initial array to the second array's length:

    a1[0...a2.size].zip(a2).take_while { |x, y| x == y }.map(&:first)