2013-11-11 7 views
0

У меня есть большой массив хэшей:массив хешей сортировать по

array = [ 
    {color: '5 absolute', ... }, 
    {color: '5.0', ... }, 
    {color: '5.1', ... }, 
    {color: 'last', ... }, 
    {color: '50', ... }, 
    {color: '5 elite', ... }, 
    {color: 'edge'} 
] 

мне нужно цвета, чтобы заказать:

5 absolute 
5 elite 
5.0 
5.1 
50 
edge 
last 

Приоритет:

first going spaces ' ', 
then dots '.', 
then digits '7', 
then other 'string' 

Это как SQL activerecord analog query, но мне не нужен этот сложный запрос в фоновом режиме. Я хочу this logic. Как это сделать, используя AR-запрос?

+0

В отсортированных данных, где вы хотите что-то '60», чтобы быть вставлен? – hirolau

+0

Да, я хочу увидеть 6 до 50 =) – asiniy

+0

Но до этого после записей с точками? – hirolau

ответ

0

так вот так?

h = [{:color=>"5 absolute"}, 
{:color=>"5.0"}, 
{:color=>"5.1"}, 
{:color=>"last"}, 
{:color=>"50"}, 
{:color=>"5 elite"}, 
{:color=>"edge"}] 

h.map(&:values).flatten.sort 
# => ["5 absolute", "5 elite", "5.0", "5.1", "50", "edge", "last"] 

или все другие ответы ...

+0

Зачем проголосовать? –

+1

Никто не знает ... – phoet

+0

ok. Как насчет 6? Это должно быть до 50 ... – asiniy

1

Вы всегда можете просто отсортировать массив хэшей.

array.map{|h| h[:color]}.sort 
=> ["5 absolute", "5 elite", "5.0", "5.1", "50", "edge", "last"] 

Следующие сначала сортируются по числу, а затем по строке после номера.

array = [{color: '5 absolute'}, {color: '5.0'}, {color: '5.1'}, 
     {color: 'last'}, {color: '50'}, {color: '5 elite'}, 
     {color: 'edge'}, {color: '6 absolute'}, {color: '7'}] 

array.map{|h| h[:color]}.sort_by do |s| 
    n = s.to_f 
    if n == 0 && s.match(/\d/).nil? 
    n = Float::INFINITY 
    end 
    [n, s.split(" ")[-1]] 
end 
=> ["5.0", "5 absolute", "5 elite", "5.1", "6 absolute", "7", "50", "edge", "last"] 
+0

Почему здесь проголосовали? –

+0

Возможно, потому, что я не предоставлял AR-запрос. –

+0

Нет, я не проголосовал здесь ... Вы видите обновленное сообщение? – asiniy

0

С вашего вопроса очень сложно сказать, чего вы хотите. Тем более, что заказ, который вы запрашиваете, точно такой же, как обычный тип.

В любом случае, здесь вы можете создать заказ «индивидуального сортировки» так, как вам хотелось. Разница между этой и обычной сортировкой заключается в том, что в этом роде могут быть созданы некоторые типы символов или множества персонажей, которые торжествуют другие.

array = [ 
    {color: '5 absolute'}, 
    {color: '5.0'}, 
    {color: '50 hello'}, 
    {color: 'edge'} 
] 
p array.sort_by{|x| x[:color]} #=> [{:color=>"5 absolute"}, {:color=>"5.0"}, {:color=>"50 hello"}, {:color=>"edge"}] 
# '50 hello' is after '5.0' as . is smaller than 0. 

Решение этой проблемы немного сложнее, вот как я бы это сделать:

# Create a custom sort order using regexp: 
# [spaces, dots, digits, words, line_endings] 
order = [/\s+/,/\./,/\d+/,/\w+/,/$/] 

# Create a union to use in a scan: 
regex_union = Regexp.union(*order) 

# Create a function that maps the capture in the scan to the index in the custom sort order: 
custom_sort_order = ->x{ 
x[:color].scan(regex_union).map{|x| [order.index{|y|x=~y}, x]}.transpose 
} 

#Sort: 
p array.sort_by{|x| custom_sort_order[x]} 
# => [{:color=>"5 absolute"}, {:color=>"50 hello"}, {:color=>"5.0"}, {:color=>"edge"}] 
Смежные вопросы