如何基于多条件优雅简洁地向数组中添加多个元素?
当然有更优雅的写法!
咱们先看看你的原代码:
def call banners = [] banners.push(banner1) if condition1? banners.push(banner2) if condition2? banners.push(banner3) if condition3? banners end def banner1 { type: BANNER1, display_value: 'banner_1' } end # 假设还有banner2、banner3方法
这段代码的核心逻辑是根据对应条件收集符合要求的banner,但重复的push和if判断显得有点冗余。下面给你几种更简洁优雅的写法:
方案1:用条件-banner配对数组 + 筛选提取
把每个条件和对应的banner打包成数组,通过筛选和映射一步得到结果:
def call [ [condition1?, banner1], [condition2?, banner2], [condition3?, banner3] ].select { |condition, _| condition }.map(&:last) end def banner1 { type: BANNER1, display_value: 'banner_1' } end # banner2、banner3方法保留
这样就去掉了重复的push和if,逻辑更集中,一眼就能看到所有条件和对应banner的关联。
方案2:内联banner定义(适合简单逻辑)
如果你的banner逻辑像例子里这么简单,完全可以把banner的哈希直接写进配对数组里,省去单独的方法:
def call [ [condition1?, { type: BANNER1, display_value: 'banner_1' }], [condition2?, { type: BANNER2, display_value: 'banner_2' }], [condition3?, { type: BANNER3, display_value: 'banner_3' }] ].select { |cond, _| cond }.map(&:last) end
行数直接减少了一半,代码更紧凑。
方案3:用Ruby 2.7+的filter_map一步到位
Ruby 2.7以后新增了filter_map方法,可以把筛选和映射合并成一步,代码更短:
def call [ [condition1?, banner1], [condition2?, banner2], [condition3?, banner3] ].filter_map { |cond, banner| banner if cond } end
filter_map会自动忽略块返回nil的元素,完美适配咱们的场景,一行搞定筛选和收集。
这些写法都保留了原逻辑的清晰度,同时大幅减少了重复代码,你可以根据banner的实际复杂度选择合适的方案~
内容的提问来源于stack exchange,提问作者prajeesh
相关产品推荐
相关产品推荐

