Eu tenho um hash que se parece com isso:
params = { :irrelevant => "A String",
:choice1 => "Oh look, another one",
:choice2 => "Even more strings",
:choice3 => "But wait",
:irrelevant2 => "The last string" }
E eu quero uma maneira simples de rejeitar todas as chaves que não são escolha + int. Pode ser escolha1 ou escolha1 através da escolha10. Varia.
Como separar as teclas com apenas a escolha da palavra e um dígito ou dígitos após elas?
Bônus:
Transforme o hash em uma string com tab (\ t) como delimitador. Eu fiz isso, mas foram necessárias várias linhas de código. Normalmente, os mestres de Rubicistas podem fazer isso em uma ou mais linhas.
Respostas:
Editar na resposta original : mesmo que essa seja a resposta selecionada (no momento deste comentário), a versão original dessa resposta está desatualizada.
Estou adicionando uma atualização aqui para ajudar outras pessoas a evitar serem desviadas por esta resposta, como eu fiz.
Como a outra resposta menciona, Ruby> = 2.5 adicionou o
Hash#slice
método que anteriormente estava disponível apenas no Rails.Exemplo:
Fim da edição. O que se segue é a resposta original, que eu acho que será útil se você estiver usando Ruby <2.5 sem Rails, embora eu imagine que esse caso seja bastante incomum neste momento.
Se você estiver usando Ruby, poderá usar o
select
método Você precisará converter a chave de um símbolo em uma string para fazer a correspondência regexp. Isso lhe dará um novo Hash com apenas as opções nele.ou você pode usar
delete_if
e modificar o Hash existente, por exemploou se são apenas as chaves e não os valores desejados, você pode fazer:
e isso dará apenas uma matriz das chaves, por exemplo
[:choice1, :choice2, :choice3]
fonte
.select
é.reject
se isso torna seu código mais idiomático.#slice
caminho funciona para mim no 2.5.3, mesmo sem o suporte ativo.No Ruby, o Hash # select é uma opção correta. Se você trabalha com Rails, pode usar Hash # slice e Hash # slice !. por exemplo (trilhos 3.2.13)
fonte
A maneira mais fácil é incluir o
gem 'activesupport'
(ougem 'active_support'
).Então, na sua turma, você só precisa
e ligar
Acredito que não vale a pena declarar outras funções que podem ter bugs, e é melhor usar um método que foi aprimorado nos últimos anos.
fonte
A maneira mais fácil é incluir a gema 'activeesupport' (ou gema 'active_support').
params.slice(:choice1, :choice2, :choice3)
fonte
Se você trabalha com trilhos e possui as chaves em uma lista separada, pode usar a
*
notação:Como outras respostas indicadas, você também pode usar
slice!
para modificar o hash no lugar (e retornar a chave / valores apagados).fonte
Esta é uma linha para resolver a questão original completa:
Mas a maioria das soluções acima está resolvendo um caso em que você precisa conhecer as chaves com antecedência, usando
slice
ou uma simples expressão regular.Aqui está outra abordagem que funciona para casos de uso simples e mais complexos, que é permutável em tempo de execução
Agora, não apenas isso permite uma lógica mais complexa na correspondência das chaves ou dos valores, mas também é mais fácil de testar, e você pode trocar a lógica correspondente no tempo de execução.
Ex para resolver o problema original:
fonte
Com
Hash::select
:fonte
Se você deseja o hash restante:
ou se você apenas quer as chaves:
fonte
Coloque isso em um inicializador
Então você pode fazer
ou
fonte
fonte
Quanto à pergunta bônus:
Se você tiver uma saída do
#select
método como este (lista de matrizes de 2 elementos):então simplesmente pegue esse resultado e execute:
Se você tiver saída do
#delete_if
método como este (hash):então:
fonte
map
leva bloco como é argumento. Você pode criar um bloco rapidamente, com&:method
construção, o que criaria um bloco{|v| v.method }
. No meu caso,&:last
foi chamado no argumento de matriz (matriz de 2 elementos). Se você quiser brincar com ele, primeiro verifique qual argumento você está recebendo no bloco (obtenha 1 argumento, não o desconstrua em vários argumentos!) E tente encontrar 1 método (com o qual você não pode encadear métodos&:method
) que retornaria o que você quer. Se for possível, você poderá usar o atalho, caso contrário, precisará de um bloco completofonte
Eu tive um problema semelhante, no meu caso, a solução era um liner que funciona mesmo que as chaves não sejam símbolos, mas você precisa ter as chaves de critério em uma matriz
Outro exemplo
fonte