2013-04-19 7 views
2

J'essayais de trier un hachage particulier par des valeurs. Je suis tombé sur un chemin en utilisant la méthode sort_by. Mais même si j'appelle sort_by un hachage, elle retourne un tableau, à savoir:Tri d'un hachage par valeurs

a = {} 
a[0] = "c" 
a[1] = "b" 
a[2] = "a" 
a.sort_by{|key, value| value} 
# => [[2, "a"], [1, "b"], [0, "c"]] 

Si je tente de convertir le résultat en un hachage, je me retrouve avec un hachage triés sur clé, donc tout le but de sort_by est perdu. i.e. .:

a = {} 
a[0] = "c" 
a[1] = "b" 
a[2] = "a" 
Hash[*a.sort_by{|key, value| value}.flatten] 
# => {0=>"c", 1=>"b", 2=>"a"} 

Est-il possible que je peux trier une table de hachage en valeur et obtenir encore les résultats de retour sous la forme d'un Hash?

EDIT: J'utilise 1.8.6 rubis

+0

dupliquer http://stackoverflow.com/questions/2455011/sort-by-values-from-hash-table-ruby – toch

+0

@toch Je ne pense pas que ce soit une question en double. La question se rapporte spécifiquement à la classification des valeurs. Mais ici, je veux retourner un résultat avec un hachage trié "sur" les valeurs. – Ricketyship

+1

Pourquoi voulez-vous utiliser un hachage? –

Répondre

1

Vous pouvez utiliser ActiveSupport::OrderedHash pour Ruby 1.8:

ActiveSupport::OrderedHash implémente un hachage qui préserve l'ordre d'insertion, comme dans Ruby 1.9

Je n'ai pas 1.8.6 fonctionnement, mais cela devrait fonctionner:

a = {} 
a[0] = "c" 
a[1] = "b" 
a[2] = "a" 

ordered = ActiveSupport::OrderedHash[*a.sort_by{|k,v| v}.flatten] 
ordered.keys 
# => [2, 1, 0], this order is guaranteed 

Comme il est indiqué dans la citation ci-dessus hash dans Ruby 1.9 « énumèrent leurs valeurs dans l'ordre que les touches correspondantes ont été insérées », donc ce n'est nécessaire pour Ruby 1.8 .

+0

Oui, un orderedHash conserve l'ordre dans lequel les éléments ont été créés. Mais le problème réside dans le fait qu'un orderedHash est à nouveau un tableau de tableaux. Je suppose qu'avec les versions inférieures de ruby, nous devons faire un compromis sur le fait que Hash ne peut pas être trié sur des valeurs et être retenu comme un type de données Hash. En outre, la solution que vous avez donnée ne fonctionnera pas car sort_by retournera toujours un tableau de tableaux. Par conséquent, créer un nouveau OrderedHash donnera un tableau de tableaux de tableaux! ;) – Ricketyship

+1

Vous avez raison, 'Hash :: []' n'accepte pas les tableaux imbriqués dans Ruby 1.8, j'ai mis à jour ma réponse. – Stefan

-2

Votre description est faux.

a = {} 
a[0] = "c" 
a[1] = "b" 
a[2] = "a" 
Hash[*a.sort_by{|key, value| value}.flatten] 

donne:

{ 
    2 => "a", 
    1 => "b", 
    0 => "c" 
} 

qui est triée par valeur. En passant, votre code est redondant. Une meilleure façon de c'est:

Hash[a.sort_by{|_, value| value}] 

ou

Hash[a.sort_by(&:last)] 

après avoir vu votre Modifier Vous utilisez une version qui n'a pas commandé de hachage. Vous ne pouvez pas contrôler l'ordre des éléments. Tu ne peux rien faire avec ça.

+0

Je l'ai essayé à nouveau après avoir commenté la description. J'ai récupéré le même hachage qui consiste à trier les données sur les clés et non sur les valeurs. Quelle version de ruby? Est-ce que la version ruby ​​a aussi de l'importance? – Ricketyship

+0

Cela devrait fonctionner comme ça tant que la version est 1.9 ou supérieure. – sawa

+0

Ok. Je suis sur 1.8.6. Edited ma question pour le même. – Ricketyship

1

Un hachage est une collection de paires clé-valeur. Il est similaire à un tableau, sauf que l'indexation est effectuée via des clés arbitraires de tout type d'objet, et non un index d'entier. L'ordre dans lequel vous parcourez un hachage par clé ou valeur peut sembler arbitraire et ne sera généralement pas dans l'ordre d'insertion .

Source: Ruby 1.8.7 docs

  • Hash préserve l'ordre. Il énumère ses éléments dans le

Source: Ruby 1.9.1 changelog

Si vous souhaitez utiliser un hachage commandé en Ruby 1.8, vous devriez regarder un soutien actif OrderedHash (Vous n'avez pas besoin d'être dans un projet rails, il suffit d'inclure un soutien actif dans votre projet)

+0

Merci pour la réponse. Mais je suppose que j'ai déjà mentionné que je veux conserver le type de données. Par conséquent, avec les versions inférieures de ruby, nous n'avons pas l'option. OrderedHash est une meilleure option cependant! À votre santé! – Ricketyship