J'ai besoin de mapper un certain nombre d'identifiants et de plages d'identifiants à des valeurs uniques. Je souhaite stocker toute la structure dans un seul objet.
Est-ce que ce qui suit est une manière sensée de le faire? Quelle est la meilleure façon de rechercher les clés par une seule valeur entière pour renvoyer la valeur correspondante?
large array = [
{[3110..3220, 10200, 43680] => 'A0300'},
{[5200, 7100..8990, 9100..9900] => 'B0400'},
{[17110..18121, 20160, 2210..22290] => 'C0600'}
]
4 réponses
Un format raisonnable pour stocker les données serait un simple hachage simple:
input = { [3110..3220, 10200, 43680] => 'A0300',
[5200, 7100..8990, 9100..9900] => 'B0400',
[17110..18121, 20160, 2210..22290] => 'C0600' }
Pour rechercher l'élément, on peut utiliser la casse égale ou triple égale. Heureusement, il est également implémenté pour les entiers:
value = 7300
result = input.detect { |k, _| k.any? { |r| r === value } }
result ? result.last : nil
#⇒ "B0400"
Il est inutile d'utiliser des tableaux et / ou des plages comme clé de hachage, lorsque vous souhaitez rechercher les données à une valeur unique. L'avantage d'un hachage est que, étant donné une clé, vous pouvez trouver une valeur rapidement. Dans votre cas, vous devrez parcourir le hachage de manière séquentielle pour trouver l'entrée. Dans ce cas, il serait plus judicieux d'utiliser un tableau de paires, le premier composant décrivant la plage et le second composant décrivant l'ID.
Si vous souhaitez utiliser un hachage, vous devez créer une entrée correspondante pour chaque valeur entière possible.
Si vous savez que les valeurs entières ne peuvent pas être supérieures à une certaine taille, vous pouvez créer un tableau fragmenté, où la valeur entière est la position d'index et l'ID est le contenu de la cellule du tableau. C'est le plus rapide, mais prend bien sûr un peu de place.
Si les valeurs étaient câblées, on pourrait utiliser une instruction case.
def look_it_up(n)
case n
when 7100..8990, 9100..9900, 5200
'B0400'
when 17110..18121, 22100..22290, 20160
'C0600'
when 3110..3220, 10200, 43680
'A0300'
else
nil
end
end
look_it_up 10200 #=> "A0300"
look_it_up 9135 #=> "B0400"
look_it_up 22100 #=> "C0600"
look_it_up 3079 #=> nil
En supposant que n
est distribué un peu uniformément, j'ai, pour des raisons d'efficacité, ordonné les clauses when
par nombre décroissant de nombres inclus, et dans chaque clause when
, j'ai mis les plages en premier et a ordonné ces gammes par taille décroissante.
Si les valeurs ne sont pas nécessairement câblées, on pourrait utiliser find/detect
, comme l'a fait @mudasobwa.
Si de nombreuses recherches devaient être effectuées, je suggérerais de construire un hachage dont les clés sont des entiers.
def init_arr(*args)
args.each do |*a, value|
a.each do |e|
if e.is_a?(Range)
e.each { |n| @h[n] = value }
else
@h[e] = value
end
end
end
end
Ensuite, pour tout n
, @h[n]
donne sa valeur. Par exemple,
@h = {}
init_arr [1..4, 8..10, 11, "cat"]
@h #=> {1=>"cat", 2=>"cat", 3=>"cat", 4=>"cat", 8=>"cat", 9=>"cat",
# 10=>"cat", 11=>"cat"}
init_arr [13..14, 7, "dog"]
@h #=> {1=>"cat", 2=>"cat", 3=>"cat", 4=>"cat", 8=>"cat", 9=>"cat",
# 10=>"cat", 11=>"cat", 13=>"dog", 14=>"dog", 7=>"dog"}
Alors dire),
@h[13]
#=> "dog"
@h[11]
#=> "cat"
@h[12]
#=> nil
Naturellement, cela suppose que @h.size
est gérable.
On pourrait aussi construire un tableau de recherche, disons @arr
, qui devrait être plus rapide que d'utiliser un hachage (bien qu'il puisse consommer beaucoup plus de mémoire qu'un hachage). @arr[n]
renverrait la valeur de n
ou nil
s'il n'y a pas de valeur correspondante. Si certaines valeurs étaient négatives, ou si les plus petites n
étaient assez grandes, on écrirait à la place @arr[n+@offset]
, où @offset
est la valeur évidente.
Non. Il n'est pas nécessaire de séparer chaque paire clé-valeur en un hachage différent comme vous l'avez fait. De plus, vous utilisez le hachage d'une manière incorrecte. Une valeur-clé de hachage n'a pas besoin d'être un-à-un. Il vaut mieux avoir quelque chose comme ça:
{
3110..3220 => 'A0300',
10200 => 'A0300',
43680 => 'A0300',
5200 => 'B0400',
7100..8990 => 'B0400',
9100..9900 => 'B0400',
17110..18121 => 'C0600',
20160 => 'C0600',
2210..22290 => 'C0600',
}
Mais je suppose que vous posez en fait une question X-Y, et ma réponse ci-dessus n'est toujours pas la meilleure solution pour vous.
Questions connexes
De nouvelles questions
arrays
Un tableau est une structure de données linéaire ordonnée constituée d'une collection d'éléments (valeurs, variables ou références), chacun identifié par un ou plusieurs index. Lorsque vous posez des questions sur des variantes spécifiques de tableaux, utilisez plutôt les balises associées: [vector], [arraylist], [matrix]. Lorsque vous utilisez cette balise, dans une question spécifique à un langage de programmation, identifiez la question avec le langage de programmation utilisé.