Como posso classificar por múltiplas condições com pedidos diferentes?

StackOverflow https://stackoverflow.com/questions/73032

  •  09-06-2019
  •  | 
  •  

Pergunta

Eu realmente gostaria de lidar com isso sem patches de macaco, mas ainda não consegui encontrar outra opção.

Eu tenho um array (em Ruby) que preciso classificar por várias condições.Eu sei como usar o método sort e usei o truque de classificação usando uma variedade de opções para classificar por múltiplas condições.Porém, neste caso preciso da primeira condição para ordenar em ordem crescente e a segunda para ordenar em ordem decrescente.Por exemplo:

ordered_list = [[1, 2], [1, 1], [2, 1]]

Alguma sugestão?

Editar:Acabei de perceber que devo mencionar que não consigo comparar facilmente o primeiro e o segundo valores (na verdade, estou trabalhando com atributos de objeto aqui).Então, para um exemplo simples, é mais parecido com:

ordered_list = [[1, "b"], [1, "a"], [2, "a"]]
Foi útil?

Solução

Que tal:


ordered_list = [[1, "b"], [1, "a"], [2, "a"]]
ordered_list.sort! do |a,b|
  [a[0],b[1]] <=> [b[0], a[1]]
end

Outras dicas

Eu estava tendo um pesadelo tentando descobrir como reverter a classificação de um atributo específico, mas normalmente classificar os outros dois.Apenas uma nota sobre a classificação para aqueles que surgem depois disso e são confusos com o | a, b | Sintaxe do bloco.Você não pode usar o {|a,b| a.blah <=> b.blah} estilo de bloco com sort_by! ou sort_by.Deve ser usado com sort! ou sort.Além disso, conforme indicado anteriormente pela troca de outros pôsteres a e b através do operador de comparação <=> para reverter a ordem de classificação.Assim:

Para classificar por blá e craw normalmente, mas classificar por bleu na ordem inversa, faça o seguinte:

something.sort!{|a,b| [a.blah, b.bleu, a.craw] <=> [b.blah, a.bleu, b.craw]}

Também é possível usar o - assinar com sort_by ou sort_by! para fazer uma classificação reversa em numerais (até onde eu saiba, ele só funciona com números, então não tente fazer isso com strings, pois isso apenas causa erros e mata a página).

Presumir a.craw é um número inteiro.Por exemplo:

something.sort_by!{|a| [a.blah, -a.craw, a.bleu]}

Eu tive esse mesmo problema básico e resolvi adicionando isto:

class Inverter
  attr_reader :o

  def initialize(o)
    @o = o
  end

  def <=>(other)
    if @o.is && other.o.is
      -(@o <=> other.o)
    else
      @o <=> other.o
    end
  end
end

Este é um wrapper que simplesmente inverte a função <=>, que permite fazer coisas como esta:

your_objects.sort_by {|y| [y.prop1,Inverter.new(y.prop2)]}

Enumerable#multisort é uma solução genérica que pode ser aplicada a matrizes de qualquer tamanho, não apenas aqueles com 2 itens.Argumentos são booleanos que indicam se um campo específico deve ser classificado em ordem crescente ou decrescente (uso abaixo):

items = [
  [3, "Britney"],
  [1, "Corin"],
  [2, "Cody"],
  [5, "Adam"],
  [1, "Sally"],
  [2, "Zack"],
  [5, "Betty"]
]

module Enumerable
  def multisort(*args)
    sort do |a, b|
      i, res = -1, 0
      res = a[i] <=> b[i] until !res.zero? or (i+=1) == a.size
      args[i] == false ? -res : res
    end
  end
end

items.multisort(true, false)
# => [[1, "Sally"], [1, "Corin"], [2, "Zack"], [2, "Cody"], [3, "Britney"], [5, "Betty"], [5, "Adam"]]
items.multisort(false, true)
# => [[5, "Adam"], [5, "Betty"], [3, "Britney"], [2, "Cody"], [2, "Zack"], [1, "Corin"], [1, "Sally"]]

Já faz algum tempo que uso a receita de Glenn.Cansado de copiar código de projeto para projeto repetidas vezes, decidi torná-lo uma joia:

http://github.com/dadooda/invert

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top