Voici une autre manière verbeuse de le faire:
order = [:col1, :col2, :col3]
cols = [:col3, :col2, :col5, :col4]
sorted_order = cols.sort_by do |c|
if order.index(c)
[1, order.index(c)]
else
[2, cols.index(c)]
end
end
p sorted_order # => [:col2, :col3, :col5, :col4]
Voici comment cela fonctionne. sort_by renvoie les éléments d'un tableau au bloc; le bloc devrait alors retourner quelque chose de comparable (techniquement, quelque chose qui répond à l'opérateur < =>). sort_by utilise le < => opérateur sur les résultats renvoyés par le bloc de décider quel ordre le tableau devrait être.
L'opérateur < => (vaisseau spatial), comme vous le savez, est un opérateur binaire prenant deux éléments a et B. Si < b, il renvoie -1. Si a == b, il renvoie 0. Si a> b, il renvoie +1.
Les tableaux répondent d'une manière non surprenante à l'opérateur < =>. Les éléments du tableau de gauche sont comparés aux éléments du tableau de droite, en commençant par l'index 0 et en augmentant. Si a [i] < => b [i] est! = 0, renvoyez ce résultat, mais si le résultat est 0, examinez l'élément suivant. Si la dernière paire d'éléments comparés est 0 (égale) et que les tableaux ont la même taille, les tableaux sont égaux et Array. < => renvoie 0, sinon le tableau le plus long est considéré plus grand (cet exemple renvoie toujours des tableaux de taille égale, cependant).
Ainsi, par exemple:
[2, 1] <=> [2, 2] == -1
[2, 2] <=> [2, 2] == 0
[2, 3] <=> [2, 2] == +1
[1, 2] <=> [2, 1] == +1
Ainsi, à l'intérieur d'un sort_by, nous pouvons utiliser les éléments d'un tableau a pour indiquer l'ordre primaire, etc. genre secondaire, tertiaire. a [0] correspond à l'ordre de tri principal, [1] correspond à l'ordre de tri secondaire, et ainsi de suite.
Toutes les colonnes spécifiées par le client doivent être les premières. Ainsi, pour chaque colonne, recherchez son index dans l'ordre spécifié par le client (order
). Si cela retourne un nombre, alors nous savons que le client a spécifié cette colonne, et nous connaissons son index dans la liste spécifiée par le client. L'ordre de tri principal est 1, car nous souhaitons que les colonnes spécifiées par le client viennent en premier; l'ordre de tri secondaire est l'index, puisque cela nous donne l'ordre que le client a spécifié les colonnes.
Si nous ne trouvons pas la colonne dans le tableau de commande (c'est-à-dire, order.index (c) renvoie zéro), alors 2 sera l'ordre de tri principal et l'index dans la liste des colonnes principales (cols
) comme ordre de tri secondaire. De cette façon, toutes les colonnes que le client n'a pas spécifiées seront les dernières, mais dans l'ordre où elles sont spécifiées dans la liste des colonnes de laster.
Je suis un peu confus au sujet de la spécification. Comment savez-vous que: col4 et: col5 ne vont pas (par exemple) au début de la liste, puisqu'ils ne font pas partie de la commande? Ou est la règle que "s'ils ne sont pas dans l'ordre, alors ils vont à la fin"? –
Si une colonne n'est pas définie dans la liste de commande, je suis invité à les mettre après les colonnes qui ont été mentionnées dans les colonnes de commande. Fondamentalement mettre: col4 et: col5 en basse priorité. – Roger