сравнить два массива, кроме элемента x, y, z (ruby) - PullRequest
4 голосов
/ 03 марта 2010

есть ли другой способ simple,nicer?

require 'pp'

a1 = ["02/28/10","Webinars","131","0","26 Feb 2010","0","3d, 8h, 49m, 18s"]
a2 = ["02/20/10","Webinars","131","9","26 Feb 2010","0","3d, 8h, 49m, 18s"]

def compare(array1,array2,ignore)

  tmp1 = Array.new
  tmp2 = Array.new
  0.upto(array1.length-1) {|index|
    if !ignore.include?(index)
      tmp1 << array1[index]
      tmp2 << array2[index]
    end
  }
  if tmp1 == tmp2 
    return true
  else
    return false    
  end
end

pp a1
pp a2
puts
puts compare(a1,a2,[0,3])

и вывод

["02/28/10", "Webinars", "131", "0", "26 Feb 2010", "0", "3d, 8h, 49m, 18s"]
["02/20/10", "Webinars", "131", "9", "26 Feb 2010", "0", "3d, 8h, 49m, 18s"]

true

Ответы [ 6 ]

7 голосов
/ 03 марта 2010

Простейший код (требуется Ruby 1.8.7 или выше):

def compare(array_a, array_b, ignore_list)
  array_a.zip(array_b).each_with_index.all? do |a, b, idx|
    a == b or ignore_list.include? idx
  end
end

Я подозреваю, что это тоже будет быстрее (поскольку он использует один zip, а не индивидуально запрашивает массив для каждого элемента) - хотя это, вероятно, не тот случай, когда скорость имеет большое значение.

Кроме того, почти каждый раз, когда я непосредственно индексирую массив (например, some_array[i]) в Ruby, а не использую метод более высокого порядка, такой как map или each, я принимаю это как знак того, что Я, вероятно, что-то упускаю в стандартной библиотеке, и алгоритм, вероятно, будет менее эффективным, чем высокооптимизированная библиотечная функция.

2 голосов
/ 03 марта 2010

Как насчет этого?

require 'enumerator'
def compare (a1, a2, i)
  a1.size == a2.size and
    ( a1.enum_for(:each_with_index).select{ |v, j| !i.include?(j)} ==
      a2.enum_for(:each_with_index).select{ |v, j| !i.include?(j)} )

end

compare([1,2,3,4,5], [1,7,6,4,5], [1,2]) #true
compare([1,2,3,4,5], [1,7,6,4,5], [1,2]) #true

Примечание Это будет работать в Ruby 1.8.6. Вы можете использовать метод Dmitriy Nagirnyak для дальнейшей оптимизации:

def compare (a1, a2, i)
  a1.size == a2.size and
    a1.enum_for(:each_with_index).all?{|v, j| a2[j] == v or i.include?(j)}
end
2 голосов
/ 03 марта 2010

Вероятно, есть много более кратких способов сделать это. Вот первое, что пришло мне в голову, и я уверен, что оно может быть улучшено.

def compare(array1, array2, ignore)
  return false if array1.size != array2.size
  0.upto(array1.size) do |i|
    return false if !ignore.include?(i) && array1[i] != array2[i]
  end
  return true
end

По сути, ручное сравнение массивов. Проверьте одинаковый размер, затем проверьте элементы один за другим (но игнорируя индексы, которые нам говорят, игнорировать). Перерыв, как только мы узнаем, что продолжать бессмысленно.

2 голосов
/ 03 марта 2010

Это выглядит лучше для меня :):

def compare(array1, array2 = [], ignore = [])
  return false if array1.length != array2.length
  array1.each_with_index.all? do |e1, i1|
    array2[i1] == e1 || ignore.include?(i1)
  end
end

Прелесть этого в том, что он "цепляет" each_with_index с all?, делая намного более чистый код.
Плохо то, что он работает только с Ruby 1.8. 7 . В любом случае не вижу смысла использовать <1.8.7 </p>

1 голос
/ 03 марта 2010

Вот решение для 1.9, в котором сравниваются массивы для <и>, а также ==:

#!/usr/bin/ruby1.9

# Return -1 if array1 < array2
#         0 if array1 == array2
#        +1 if array1 > array2
# ignore contains indices of elements to ignore

def compare(array1, array2, ignore)
  filter = lambda do |a|
    a.collect.with_index do |e, i|
      if ignore.include?(i)
        ''
      else
        e
      end
    end
  end
  filter[array1] <=> filter[array2]
end

array1 = ["02/28/10","Webinars","131","0","26 Feb 2010","0","3d, 8h, 49m, 18s"]
array2 = ["02/20/10","Webinars","131","9","26 Feb 2010","0","3d, 8h, 49m, 18s"]

p compare(array1, array2, [0, 3])    # => 0
p compare(array1, array2, [0])       # => -1
p compare(array1, array2, [3])       # => 1
0 голосов
/ 03 марта 2010

Вот еще один, краткий и крайне неэффективный:

def compare a1, a2, i
  [a1,a2].map { |a|
    a.values_at(*((0...a.length).to_a - i))
  }.inject(&:==)
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...