2011-11-14 16 views
8

que tienen una matriz que tiene el siguiente aspecto:¿Cómo realizo una clasificación personalizada compleja en Ruby?

[ 
    { type: 'A', price: '0.01' }, 
    { type: 'B', price: '4.23' }, 
    { type: 'D', price: '2.29' }, 
    { type: 'B', price: '3.38' }, 
    { type: 'C', price: '1.15' } 
] 

que necesitan agrupar éstos por type y luego ordenarlos por orden ascendente price. Puedo medio de resolver este problema de la siguiente manera:

boards.sort_by {|e| [e['type'], e['price'].to_f]} 

Por desgracia, este ordena la type s alfabéticamente cuando deberían estar ordenados BADC

¿Cómo puedo ordenar la matriz por las reglas predeterminadas?

+1

la pregunta no está clara: ¿cuál es el resultado deseado? para productos del mismo tipo, ¿obtiene el que tiene el precio más bajo? y luego siempre ordena por PRECIO ASC? – tokland

+1

Creo que quiere ordenar por tipo, y cuando el tipo es igual, quiere ordenar por precio. – sheldonh

+0

@sheldonh. pero eso es exactamente lo que hace su código. Luego dice que la salida debe ordenarse "BADC", lo cual no tiene sentido (no hay precio ni orden de tipo allí ...) pero en cualquier caso parece que el tipo B se ha agrupado, por lo que realmente quiere agruparlo. Quién sabe ... – tokland

Respuesta

14
ar=[ 
    { type: 'A', price: '0.01' }, 
    { type: 'B', price: '4.23' }, 
    { type: 'D', price: '2.29' }, 
    { type: 'B', price: '3.38' }, 
    { type: 'C', price: '1.15' } 
] 

SORT_ORDER = 'BADC' #could also be an array, eg ["monday", "tuesday", ...] 
p ar.sort_by{|e| [SORT_ORDER.index(e[:type]), e[:price].to_f]} 

Salida:

[{:type=>"B", :price=>"3.38"}, 
{:type=>"B", :price=>"4.23"}, 
{:type=>"A", :price=>"0.01"}, 
{:type=>"D", :price=>"2.29"}, 
{:type=>"C", :price=>"1.15"}] 
+0

Creo que por "BADC" el OP significa la salida esperada, no es que este lo sepa de antemano. Pero la pregunta no está clara. – tokland

2

[editar] La pregunta no está clara. Eso es lo que entiendo: ordene tableros por price ASC pero para tableros del mismo tipo, obtenga solo los más baratos. El uso de la abstracción Enumerable#uniq_by Facetas (también en ActiveSupport: Array#uniq_by):

require 'facets' 
boards.sort_by { |b| p[:price].to_f }.uniq_by { |b| b[:type] } 

Salida:

[{:type=>"A", :price=>"0.01"}, 
{:type=>"C", :price=>"1.15"}, 
{:type=>"D", :price=>"2.29"}, 
{:type=>"B", :price=>"3.38"}] 
1

La utilización del término "grupo por" es confundir a la gente

Si desea ordenar por tipo, y si el tipo es igual a continuación, ordenar por precio, usted puede hacer esto:

boards.sort do |a, b| 
    type_order = a[:type] <=> b[:type] 
    if type_order != 0 
    type_order 
    else 
    a[:price] <=> b[:price] 
    end 
end 

Si no es así, tendrá que explicar mejor lo que quiere. :-)

Cuestiones relacionadas