Сортировка вложенного хэша в ruby - PullRequest
3 голосов
/ 20 апреля 2010

Предоставляется следующий рубиновый хеш:

{
    cat: {
        1: 2,
        2: 10,
        3: 11,
        4: 1
    },
    wings: {
        1: 3,
        2: 5,
        3: 7,
        4: 7
    },
    grimace: {
        1: 4,
        2: 5,
        3: 5,
        4: 1
    },
    stubborn: {
        1: 5,
        2: 3,
        3: 7,
        4: 5
    }
}

Как я могу отсортировать хеш по сумме «листьев», исключая «4», например, значение для сравнения для «кошки» будет (2 + 10 + 11) = 23, значение для «крыльев» будет be (3 + 5 + 7) = 15, поэтому, если бы я сравнивал только эти два, они были бы в правильном порядке, самая высокая сумма сверху.

Можно с уверенностью предположить, что ВСЕГДА будет {1: значение, 2: значение, 3: значение, 4: значение}, так как это ключи для определенных мной констант.

Можно также с уверенностью предположить, что я когда-нибудь захочу исключить только клавишу «4» и всегда использовать клавиши «1», «2» и «3»

По предложению Джордана я получил это на работу:

  tag_hash = tag_hash.sort_by do |h| 
    h[1].inject(0) do |sum, n| 
      n[0] == 4 ? sum : sum + (n[1] || 0)
    end
  end

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

Я обновил свое решение, чтобы использовать идею Уэйна Конрада, см. Мой комментарий к его ответу - возможно ли, что он не несет все, когда сортирует, я связал изображение в своем комментарии, который показывает результат фактической сортировки в виде графика .. мне кажется странным ..

Ответы [ 4 ]

8 голосов
/ 20 апреля 2010
tag_hash = tag_hash.sort_by do |_, leaf|
  leaf.reject do |key, _|
    key == 4
  end.collect(&:last).inject(:+)
end
2 голосов
/ 20 апреля 2010
my_hash.sort_by do |_, h|
  h.inject(0) do |sum, n|
    # only add to the sum if the key isn't '4'
    n[0] == 4 ? sum : (sum + n[1])
  end
end

Это, конечно, можно сократить до ужасно нечитаемого однострочного:

my_hash.sort_by {|k,h| h.inject(0) {|sum,n| n[0] == 4 ? sum : (sum + n[1]) } }
0 голосов
/ 24 апреля 2010

Это похоже на работу:

x.sort_by{ |_,h| h.values.take(3).inject(:+) }

Предполагается, что субшиши отсортированы (первые три записи - это записи, которые вы хотите суммировать).

Когда вы используете ActiveSupport, вы можете сделать это:

x.sort_by{ |_,h| h.values.take(3).sum }

или

x.sort_by{ |_,h| h.slice(1,2,3).values.sum }

Hash # slice возвращает хеш, содержащий только ключи, переданные в slice. Array # take возвращает массив, содержащий первые n записей исходного массива.

(Требуется Ruby 1.9.1, я думаю)

0 голосов
/ 20 апреля 2010

Это

puts a.sort_by { |k, v| -v.values[0..-1].inject(&:+) }

производит следующий вывод, это было то, что вы хотели?

cat
{1=>2, 2=>10, 3=>11, 4=>1}
wings
{1=>3, 2=>5, 3=>7, 4=>7}
stubborn
{1=>5, 2=>3, 3=>7, 4=>5}
grimace
{1=>4, 2=>5, 3=>5, 4=>1}
...