2010-03-03 4 views
4

est-il une autre façon simple,nicer?comparer deux réseaux à l'exception de l'élément x, y, z (rubis)

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]) 

et la sortie est

["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 
+1

pour votre information, la version en question revient toujours vrai, parce que tmp1 et le point de tmp2 au même tableau. Essayez de comparer ([0], [1], []) –

+0

merci de le signaler. Fixé. – Radek

Répondre

2

Il y a probablement beaucoup de façons plus concis de le faire. Voici la première qui m'est venue à l'esprit et qui, j'en suis sûr, pourrait être améliorée.

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 

Essentiellement, une comparaison de tableaux manuelle. Vérifiez la même taille, puis vérifiez les éléments un par un (en ignorant les indices qu'on nous dit d'ignorer). Pause dès que nous savons qu'il est inutile de procéder.

+0

@Matchu: super! cela fonctionne très bien :-) juste une clarification de plus pour moi de comprendre votre code. Une fois que la fonction compare frappe le retour, elle ne continue pas à exécuter le code mais quitte la fonction. Est-ce correct? – Radek

+0

C'est correct :) Je ne veux plus faire de vérification une fois que nous saurons quelle sera la fonction. – Matchu

+0

@Matchu: merci. Pour les deux :-) – Radek

2

Cela me semble mieux :):

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 

La beauté de cela est qu'il "chaînes" each_with_index avec all? rendre le code plus propre .
La mauvaise est qu'il ne fonctionne que de Ruby 1.8. . Quoi qu'il en soit ne voient pas une raison d'utiliser < 1.8.7

+1

Je n'aime pas que cela mute les tableaux d'origine. – Matchu

+0

Ce n'est plus le cas. –

+0

@Dmitriy Nagirnyak: votre code me donne une erreur 'each_with_index ': pas de bloc donné (LocalJumpError) mais surtout j'ai essayé déjà. delete_at (i) fait que le deuxième élément du tableau ignore sera incorrect car les index vont changer. Et aussi il va modifier le tableau original passé en argument.Bien sûr, je peux utiliser un tableau tmp. – Radek

7

Code Simplest (nécessite Ruby 1.8.7 ou plus):

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 

Je soupçonne que ce sera plus rapide aussi (car il utilise un seul zip plutôt que de demander individuellement le tableau pour chaque élément) - si ce n'est probablement pas un cas où la vitesse compte beaucoup.

En aparté, presque chaque fois que je suis indexation directement un tableau (comme some_array[i]) en Ruby plutôt que d'utiliser une méthode d'ordre supérieur tels que map ou each, je prends cela comme un signe que je suis probablement manquer quelque chose dans la bibliothèque standard et l'algorithme sera probablement moins efficace que la fonction de bibliothèque hautement optimisée.

+0

Bon. J'ai oublié 'zip' dans Ruby. Mais d'où vient le bloc avec 3 arguments pour 'tout?'. Le code ci-dessous écrit 'nil' pour moi, ce qui signifie que' a' est un élément, 'b' est un index. 'idx' n'est pas défini: ' [1,2] .zip (['a', 'b']). each_with_index.all? {| a, b, idx | met idx; vrai} ' –

2

Comment cela?

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 

Remarque Cela fonctionne dans Ruby 1.8.6. Vous pouvez utiliser la méthode de Dmitriy Nagirnyak pour optimiser cet autre:

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 
+0

wow. laissez-moi vérifier ... – Radek

+0

@KandadaBoggu: il me donne faux, mais devrait donner vrai ... – Radek

+0

Quelle est la valeur dont vous avez besoin? Si vous voulez que ce soit faux quand il correspond, annulez le résultat. –

1

est ici une solution pour 1,9 qui compare les tableaux pour < et> ainsi que ==:

#!/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

Voici un autre, laconique et très inefficace:

def compare a1, a2, i 
    [a1,a2].map { |a| 
    a.values_at(*((0...a.length).to_a - i)) 
    }.inject(&:==) 
end 
Questions connexes