2009-12-23 6 views
0

Un utilisateur a défini l'ordre des colonnes dans un tableau.Tableau de tri en ruby ​​

order = [:col1, :col2, :col3] 

Depuis les colonnes définies par l'utilisateur commande l'état de la table a changé et la liste actuelle des colonnes est

cols = [:col1, :col4, :col3, :col5] 

Avec les cols de commande donné besoin de tri. Dans ce cas, les colonnes triées pourraient ressembler à l'un de ces deux cas.

[:col2, :col3, :col4, :col5] 
[:col2, :col3, :col5, :col4] 

Voici mon code pour le faire fonctionner. Vous vous demandez s'il y a un meilleur moyen.

#get rid of :col2 since it is not present in the cols listing 
sanitized_order = order - (order - cols) 

sorted_cols = sanitized_order + (cols - sanitized_order) 
+0

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"? –

+0

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

Répondre

2

Que voulez-vous dire par mieux? Vous avez déjà accompli votre tâche assez facilement.

1) Ceci est comme le vôtre mais 1 ligne lisible.

#order & cols -> provides unique items found in both 
#cols - order -> provides columns that are in cols but not order 
sorted_cols = (order & cols) + (cols - order) 

2) est ici d'une manière qui se lit plus comme un livre si quelqu'un pouvait le suivre ligne par ligne pour voir la logique au lieu de déterminer les différences entre les tables:

order = [:col1, :col2, :col3] 
cols = [:col1, :col4, :col3, :col5] 

sanitized_order = [] 

order.each do |column| 
    if cols.include?(column) then 
    sanitized_order << column 
    cols.delete(column) 
    end 
end 

cols.each do |remainingcolumn| 
    sanitized_order << remainingcolumn 
end 

puts sanitized_order 
0

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.

+0

cool. Cela fonctionnera. Cependant je pense que ce n'est pas si évident ce qui se passe. – Roger

+0

J'ai ajouté une explication. J'espère que ça aide. –