2010-04-14 4 views

Répondre

119

Dans votre exemple

a.sort 

est équivalent à

a.sort { |x, y| x <=> y } 

Comme vous le savez, pour trier un tableau, vous devez être en mesure pour comparer ses éléments (si vous en doutez, essayez d'implémenter n'importe quel algorithme de tri sans utiliser de comparaison n ° <, >, <= ou >=).

Le bloc que vous fournissez est en fait une fonction qui sera appelée par l'algorithme sort pour comparer deux éléments. Soit x et y seront toujours des éléments du tableau d'entrée choisi par l'algorithme sort lors de son exécution.

L'algorithme sort suppose que cette fonction de comparaison/bloc répondra aux exigences de procédé <=>:

  • retour -1 si x < y
  • retour 0 si x = y
  • retour 1 si x> y

Le défaut de fournir une fonction/un bloc de comparaison adéquat résultera en un tableau dont der est indéfini.

Vous devriez maintenant comprendre pourquoi

a.sort { |x, y| x <=> y } 

et

a.sort { |x, y| y <=> x } 

retour le même tableau des commandes opposées.


décrire en détail la Tate Johnson a ajouté, si vous implémentez la fonction de comparaison <=> sur vos cours, vous gagnez la

suivante
  1. Vous pouvez inclure le module Comparable dans votre classe qui sera automatiquement définir pour vous les méthodes suivantes: between?, ==, >=, <, <= et >.
  2. Les instances de votre classe peuvent maintenant être triées en utilisant l'appel par défaut (c'est-à-dire sans argument) à sort.

Notez que la méthode <=> est déjà prévu où il est logique dans la bibliothèque standard de Ruby (Bignum, Array, File::Stat, Fixnum, String, Time, etc ...).

+1

Je pense qu'il vaut la peine que '<=> ajoutant' est une méthode définie dans 'Comparable' et mélangé avec' CHAINE'. '' Fixnum' et Bignum' définissent également '' <=>. Vous pouvez mettre en œuvre '' <=> dans une classe où le tri ou comparrisons sont nécessaires. –

+0

J'ai souligné la phrase importante. x et y seront 2 éléments de votre tableau, choisis par l'algorithme de tri lui-même. – bltxd

+0

Merci. Je l'ai maintenant! –

6

<=> est un procédé rubis qui retourne (self.<=>(argument))

  • -1 si l'argument auto <
  • 0 si l'argument self ==
  • 1 si auto> argumentation

x et y sont des éléments de tableau. Si aucun bloc n'est fourni, la fonction sort utilise x<=>y, sinon le résultat du bloc indique si x doit être avant y.

array.sort{|x, y| some_very_complicated_method(x, y) } 

ici si some_very_complicated_method (x, y) retourne lissée qui est < 0, x est considéré comme < que y et ainsi de suite ...

20

Lorsque vous avez un tableau de, disons, les nombres entiers trier, c'est assez simple pour sort méthode pour ordonner les éléments correctement - plus petits nombres d'abord, plus grand à la fin. C'est quand vous utilisez sort ordinaire, sans bloc. Mais lorsque vous triez d'autres objets, il peut être nécessaire de fournir un moyen de comparer (chacun) deux d'entre eux. Disons que vous avez un tableau d'objets de la classe Person. Vous ne pouvez probablement pas dire si l'objet bob est supérieur à l'objet mike (c'est-à-dire que la classe Person ne possède pas la méthode <=> implémentée). Dans ce cas, vous devrez fournir du code pour expliquer dans quel ordre vous souhaitez que ces objets soient triés en fonction de la méthode sort. C'est là la forme de blocs entre en jeu

people.sort{|p1,p2| p1.age <=> p2.age} 
people.sort{|p1,p2| p1.children.count <=> p2.children.count} 

etc. Dans tous ces cas, la méthode sort les trie de la même manière -. Le même algorithme est utilisé. Ce qui est différent est la logique de comparaison.

+0

Trouvé cette réponse beaucoup plus utile pour être honnête. Une image parle mille mots et un exemple parle mille lignes d'explication. –

+0

Note: 'people.sort {| p1, p2 | p1.age <=> p2.age} 'pourrait être réécrit comme' people.sort_by {| p | p.age} ' – Cyoce

4

Quelques points divers:

  • x et y sont appelés paramètres de bloc. La méthode de tri dit essentiellement "Je vais vous donner x et y, vous déterminez si x ou y devrait venir en premier, et je vais m'occuper des choses ennuyeuses en ce qui concerne le tri"
  • <=> est appelé spaceship operator.
3

Dans:

a.sort {|x,y| y <=> x } #=> ["e", "d", "c", "b", "a"] 

ce qui est x et y?

x et y sont les éléments qui sont comparés par l'algorithme de tri.

Ceci est utile pour définir des classes personnalisées quel élément devrait être avant l'autre.

Pour les données de base (nombres, chaînes, date, etc.) l'ordre naturel est prédéfini, mais pour l'élément client (des employés) vous définissez qui précède qui, dans une comparaison. Ce bloc vous donne l'opportunité de le définir.

et que se passe-t-il à y < => x?

Là, ils comparent les éléments dans l'ordre décroissant (ceux ayant une valeur « supérieure » ira d'abord) plutôt que l'ordre naturel (x<=>y)

La méthode <=> signifie « compareTo » et retour 0 si les éléments sont équivalents ou < 0 si x avant que y passe ou > 0 si x va après y

2

Je crois | x, y | y < => x compare deux éléments à la fois dans l'ordre décroissant, comme suit: http://www.ruby-doc.org/core-1.9.3/Array.html#method-i-3C-3D-3E Dire avec ["d", "a", "e", "c", "b"], "d" et "a" semble être comparé en premier. Puisqu'il est descendant, les deux restent dans le même ordre parce que d évalue à moins de a. Alors d et e sont évalués. "e" est déplacé à la position "d". Sans connaître le fonctionnement interne du code c, il n'est pas possible de savoir où est déplacé, mais je pense que ce processus continue jusqu'à ce que tous les éléments soient triés. Les fonctions c:

  VALUE 
rb_ary_cmp(VALUE ary1, VALUE ary2) 
{ 
    long len; 
    VALUE v; 

    ary2 = rb_check_array_type(ary2); 
    if (NIL_P(ary2)) return Qnil; 
    if (ary1 == ary2) return INT2FIX(0); 
    v = rb_exec_recursive_paired(recursive_cmp, ary1, ary2, ary2); 
    if (v != Qundef) return v; 
    len = RARRAY_LEN(ary1) - RARRAY_LEN(ary2); 
    if (len == 0) return INT2FIX(0); 
    if (len > 0) return INT2FIX(1); 
    return INT2FIX(-1); 
} 
7

@OscarRyz en réplique ont permis de dissiper beaucoup pour moi sur la question sur la façon dont le genre fonctionne, esp

{ |x, y| y <=> x } 

Sur la base de ma compréhension, je suis fournirai ici ce que l'état de la tableau serait après chaque comparaison pour les résultats de bloc ci-dessus.

Note: A obtenu avec la référence de l'impression des valeurs de paramaters de blocs e1, e2 de ruby-forum

1.9.3dev :001 > a = %w(d e a w f k) 
1.9.3dev :003 > a.sort { |e1, e2| p [e2, e1]; e2 <=> e1 } 
["w", "d"] 
["k", "w"] 
["k", "d"] 
["k", "e"] 
["k", "f"] 
["k", "a"] 
["f", "a"] 
["d", "f"] 
["d", "a"] 
["d", "e"] 
["e", "f"] 
=> ["w", "k", "f", "e", "d", "a"] 

A deviné état de réseau lors de l'exécution, après chaque comparaison:

[e2, e1] Comparsion Result  Array State 
["w", "d"]  1     ["w", "e", "a", "d", "f", "k"] 
["k", "w"]  -1     ["w", "e", "a", "d", "f", "k"] 
["k", "d"]  1     ["w", "e", "a", "k", "f", "d"] 
["k", "e"]  1     ["w", "k", "a", "e", "f", "d"] 
["k", "f"]  1     ["w", "k", "a", "e", "f", "d"]  
["k", "a"]  1     ["w", "k", "a", "e", "f", "d"] 
["f", "a"]  1     ["w", "k", "f", "e", "a", "d"] 
["d", "f"]  -1     ["w", "k", "f", "e", "a", "d"] 
["d", "a"]  1     ["w", "k", "f", "e", "d", "a"] 
["d", "e"]  -1     ["w", "k", "f", "e", "d", "a"] 
["e", "f"]  -1     ["w", "k", "f", "e", "d", "a"] (Result) 

Merci,

Jignesh