Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

276
Visualizações
How to append a unique array of struct based on an attribute?

I have an array of structs and I need to keep them unique based on an attribute, :num. This array will be appended with new struct objects. If the new struct object has a duplicate :num attribute value, I want to remove the old element containing duplicate :num and replace it with the new one.

Here's what I mean. Let's set it up:

Gen = Struct.new(:num, :val)
arr = []
arr << Gen.new(11, "foo1")
arr << Gen.new(12, "foo2")

# [#<struct num=11, val="foo1">, #<struct num=12, val="foo2">]

Then I feed it with new structs. Let's construct them:

s1 = Gen.new(12, "foo10")
s2 = Gen.new(13, "foo3")
  • If I do arr << s1, it will just append s1 into arr.
  • If I do arr.uniq {|el| el.number} after I did the above, it sometimes remove "foo10", but I want to always keep the latest struct.

When s1 is appended into arr, it needs to replace the old #<struct num=12, val="foo2"> struct because s1 is the newest feed. Since arr already contains :num 12, we need to replace it with the new struct. Since s2 contains a unique :num, it should be able to be appended no problem (even should s2 contain a duplicate :val, it should not matter, I am only concerned with keeping :num unique).

In the end, I need arr to look like:

[#<struct num=11, val="foo1">, #<struct num=12, val="foo10">, #<struct num=13, val="foo3">]

The order of the array doesn't matter.

I've looked at Add element to an array if it's not there already, Ruby condition for inserting unique items into an array, Remove duplicate elements from array in Ruby , and a few other posts. They are all mostly dealing with simple array, not array of structs.

How can I achieve this?

over 4 years ago · Santiago Trujillo
2 Respostas
Responde à pergunta

0

It's easiest to maintain a hash whose keys are the values of :num and whose values are the associated struct. The hash (h) can be updated with a new struct (st) in the desired manner as follows.

def add_struct(h, st)
  h.update(st[:num]=>st)
end

Then when an array of current structs is required simply return the values of the hash.

See Hash#update (aka merge!). Recall that if hashes h and g both have a key k, the value of k in the hash h.update(g) (or h.merge(g)) equals g[k]. h.update(st[:num]=>st) is shorthand for h.update({ st[:num]=>st }). The return value of add_struct is the updated value of h.

Here's an example.

Gen = Struct.new(:num, :val)
s1 = Gen.new(11, "foo1")
  #=> #<struct Gen num=11, val="foo1">
s2 = Gen.new(12, "foo2")
  #=> #<struct Gen num=12, val="foo2">
s3 = Gen.new(12, "foo10")
  #=> #<struct Gen num=12, val="foo10">
s4 = Gen.new(13, "foo3")
  #=> #<struct Gen num=13, val="foo3">
h = {}
add_struct(h, s1)
  #=> {11=>#<struct Gen num=11, val="foo1">}
add_struct(h, s2)
  #=> {11=>#<struct Gen num=11, val="foo1">,
  #    12=>#<struct Gen num=12, val="foo2">}
add_struct(h, s3)
  #=> {11=>#<struct Gen num=11, val="foo1">,
  #    12=>#<struct Gen num=12, val="foo10">}
add_struct(h, s4) 
  #=> {11=>#<struct Gen num=11, val="foo1">,
  #    12=>#<struct Gen num=12, val="foo10">,
  #    13=>#<struct Gen num=13, val="foo3">}
h #=> {11=>#<struct Gen num=11, val="foo1">,
  #    12=>#<struct Gen num=12, val="foo10">,
  #    13=>#<struct Gen num=13, val="foo3">} 
h.values
  #=> [#<struct Gen num=11, val="foo1">,
  #    #<struct Gen num=12, val="foo10">,
  #    #<struct Gen num=13, val="foo3">]
over 4 years ago · Santiago Trujillo Relatório

0

Take the new gens one by one. Find the corresponding old gen and let it have the new one's vualue. If no old gen is found, add the complete new gen.

Gen = Struct.new(:num, :val) 
arr = []
arr << Gen.new(11, "foo1")
arr << Gen.new(12, "foo2")

new_gens = [Gen.new(12, "foo10"),
            Gen.new(13, "foo3")]
#let's go
new_gens.each do |new_gen|
  match = arr.detect{|old_gen| old_gen.num == new_gen.num}
  match ? match.val = new_gen.val : arr << new_gen
end
  
p arr # =>[#<struct num=11, val="foo1">, #<struct num=12, val="foo10">, #<struct num=13, val="foo3">]
over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda