You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ruby中如何基于指定属性向结构体数组追加元素,重复时替换旧值

方案1:封装自定义追加方法(保持数组原生结构)

直接封装操作方法,插入新元素前先删除所有同:num的旧元素,再追加新元素即可,逻辑直观无额外依赖:

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

# 自定义追加替换方法,直接修改原数组
def append_or_replace!(arr, new_obj)
  # 删除所有num属性匹配的旧元素
  arr.delete_if { |item| item.num == new_obj.num }
  # 追加新元素
  arr << new_obj
end

# 测试用例
s1 = Gen.new(12, "foo10")
s2 = Gen.new(13, "foo3")

append_or_replace!(arr, s1)
append_or_replace!(arr, s2)

p arr
# 输出符合预期:[#<struct Gen num=11, val="foo1">, #<struct Gen num=12, val="foo10">, #<struct Gen num=13, val="foo3">]

方案2:Hash中间存储(适合高频操作场景,性能更优)

如果需要频繁执行追加替换操作,每次遍历数组的O(n)开销过高,可以直接用:num作为Hash的键,结构体作为值,天然支持同键覆盖,需要数组时直接取values即可:

Gen = Struct.new(:num, :val)
# 用Hash存储,key为num属性,自动去重
data = {}
data[11] = Gen.new(11, "foo1")
data[12] = Gen.new(12, "foo2")

# 新增元素直接赋值,同key自动覆盖旧值
s1 = Gen.new(12, "foo10")
s2 = Gen.new(13, "foo3")
data[s1.num] = s1
data[s2.num] = s2

# 转换为数组
arr = data.values
p arr
# 输出符合预期:[#<struct Gen num=11, val="foo1">, #<struct Gen num=12, val="foo10">, #<struct Gen num=13, val="foo3">]

补充说明

你之前使用uniq会丢失新元素的原因有两个:

  1. 代码存在属性名错误:你的结构体定义的属性是num不是number,原写法arr.uniq {|el| el.number}会直接抛出无方法错误
  2. uniq默认保留第一个出现的匹配元素,就算修正属性名,追加新元素后再去重会保留旧值,如果你非要用uniq实现,可以把新元素插在数组头部再去重:arr.unshift(s1).uniq! { |el| el.num },但该方法会打乱数组原有顺序,性能也不如前两种方案,不推荐使用。

内容的提问来源于stack exchange,提问作者Iggy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 16:54:03