Je cherche à voir si un tableau a une ou plusieurs valeurs à l'intérieur. Par exemple, quelque chose comme ça:
[1,2,3,4,5,6].include?([4,1]) # => true
[4,1,6,2].include?([4,1]) # => true
[3,4,7].include?([4,1]) # => false
Bien sûr, le "inclure?" méthode ne peut vérifier qu'une valeur. Existe-t-il une méthode pour vérifier plusieurs valeurs?
EDIT: J'approuve Mark Thomas ' Solution alternative utilisant la version de base Set
class .
Bien que ma solution réponde plus strictement à la question de savoir comment procéder à l'aide de tableaux, sjsc peut tirer avantage de la révision de son propre cas et de l'exploration de l'option consistant à utiliser des ensembles.
Il y a beaucoup de raisons valables pour utiliser des tableaux (maintien de l'ordre, permettant des doublons), pour lesquels les éléments ci-dessous sont encore suffisants, mais si aucun de ceux-ci n'est impliqué, sjsc pourrait en réalité tirer avantage de l'utilisation de Set au lieu de Array, et dans cette mesure, la solution est sémantiquement supérieure.
Je ne connais aucune méthode de bibliothèque qui effectue cela, mais il ne serait pas trop difficile d'écrire votre propre fonction.
class Array
def subset?(a)
(self - a).length == 0
end
end
Je suis sûr qu'il existe des moyens informatiques plus efficaces pour accomplir cela, mais cela devrait faire ce que vous cherchez.
Faire une intersection de tableau fonctionne et revient en gros à la même chose.
class Array
def subset?(a)
(self & a).length == length
end
end
L’optimisation à ce niveau n’aidera pas beaucoup, mais vous ne voudrez pas commencer à comparer les tableaux plusieurs fois:
class Array
# don't do this
def subset?(a)
(self & a) == a
end
end
>> [1,2,3,4,5,6] & [4,1]
=> [1, 4]
>> [1,2,3,4,5,6] & [7,9]
=> []
>>
Ceci est une opération définie. Set
est dans la bibliothèque standard.
require 'set'
a = Set[1,2,3,4,5,6]
b = Set[4,1]
b.subset? a
#=> true
Une extension rapide et sale de l'approche de @ Schwartzie:
larger_array = [1,2,3,4,5,6]
smaller_array = [4,1]
smaller_array.all? {|smaller_array_item| larger_array.include?(smaller_array_item)}
Sur la base de la suggestion de kurumi et de spyle, voici mon test:
([1,2,3,4,5,6] & [4,1]). # => true
Cependant. transformera tous les objets en vrais
([1,2,3,4,5,6] & [6,7]). # => true
Donc, je pense que cela pourrait être un travail:
([1,2,3,4,5,6] & [6,7]). Length == [6,7] .length # => false
(larger_array & smaller_array) .length == smaller_array.length
Quel est le problème avec [1,2,3,4,5,6].include?(4) and [1,2,3,4,5,6].include?(1)
?
J'aime la réponse de Kurumi, mais juste pour en lancer une de plus:
>> set1 = [1,2,3,4,5,6]
[
[0] 1,
[1] 2,
[2] 3,
[3] 4,
[4] 5,
[5] 6
]
>> set2 = [4,1]
[
[0] 4,
[1] 1
]
>> set1.any?{ |num| set2.include?(num) }
true
>> set2 = [8,9]
[
[0] 8,
[1] 9
]
>> set1.any?{ |num| set2.include?(num) }
false
Ma conclusion est que la méthode soustraction est généralement agréable, mais que les objets réels Set sont extrêmement rapides car ils sont clairement optimisés pour ce type de calcul.
Utilisation de ce script: https://Gist.github.com/1996001
J'ai eu ces résultats de référence (sur Ruby 1.9.2p290):
SUBTRACTION
- subset
0.180000 0.000000 0.180000 ( 0.189767)
- partial subset
0.170000 0.000000 0.170000 ( 0.178700)
- non subset
0.180000 0.000000 0.180000 ( 0.177606)
INTERSECTION
- subset
0.190000 0.000000 0.190000 ( 0.194149)
- partial subset
0.190000 0.000000 0.190000 ( 0.191253)
- non subset
0.190000 0.000000 0.190000 ( 0.195798)
SET
- subset
0.050000 0.000000 0.050000 ( 0.048634)
- partial subset
0.040000 0.000000 0.040000 ( 0.045927)
- non subset
0.050000 0.010000 0.060000 ( 0.052925)
Ce que je considère assez surprenant, surtout si vous consultez la source:
# File 'lib/set.rb', line 204
def subset?(set)
set.is_a?(Set) or raise ArgumentError, "value must be a set"
return false if set.size < size
all? { |o| set.include?(o) }
end
via: http://rubydoc.info/stdlib/set/1.9.2/Set#subset%3F-instance_method
@kurumi a raison, mais je pensais ajouter que j'utilise parfois cette petite extension quand je ne veux qu'un sous-ensemble d'un tableau (généralement les clés de hachage):
class Hash
# Usage { :a => 1, :b => 2, :c => 3}.except(:a) -> { :b => 2, :c => 3}
def except(*keys)
self.reject { |k,v|
keys.include? k
}
end
# Usage { :a => 1, :b => 2, :c => 3}.only(:a) -> {:a => 1}
def only(*keys)
self.dup.reject { |k,v|
!keys.include? k
}
end
end
class Array
def except(*values)
self.reject { |v|
values.include? v
}
end
def only(*values)
self.reject { |v|
!values.include? v
}
end
end
Simple et meilleur moyen:
([4,1] - [1,2,3,4,5,6]). Vide? # => true
([4,1] - [4,1,6,2]). Vide? # => true
([4,1] - [3,4,7]). Vide? # => faux
Pour vérifier les valeurs de tableau contenant un ou plusieurs éléments, vous pouvez convertir un tableau sur "set", puis utiliser "subset?" méthode comme ci-dessous.
require "set"
a = [1,2,3,4,5,6]
b = [3,6]
b.to_set.subset?a.to_set //true
b= [3,7]
b.to_set.subset?a.to_set //false
Ceci vérifiera si un élément existe dans un tableau:
students = ["jim", "bob", "sally"]
teachers = ["mrs. jones", "mrs. sharpe", "mrs. ray"]
puts "what's your name ?"
answer = gets.chomp
if answer.include?(students.to_s)
puts "you are a student"
elsif
puts "you are a teacher"
end