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

如何利用嵌套数组数据创建Ruby Supplies类的实例?

修正Ruby商品实例创建代码的方案

我来帮你搞定这段代码的问题,你的需求是把爬虫返回的嵌套数组转换成一个个独立的Catalog::Supplies实例,同时用类变量保存所有实例对吧?先说说原代码里的几个核心问题:

原代码的问题点

  • 索引越界风险:原while循环的条件count <= name_url_price[0].length会让count走到数组长度的位置,而数组索引是从0到length-1的,这时候访问name_url_price[0][count]会拿到nil,甚至触发报错。
  • 实例重复赋值:你在initialize里反复修改同一个实例的属性,然后多次把它加到@@all里——最后@@all里的元素其实都是同一个对象,属性只会保留最后一个商品的值,完全达不到每个商品对应一个实例的目的。

修正后的实现方案

我推荐把单个实例的初始化和批量创建逻辑分开,这样代码更清晰,也符合面向对象的设计原则:

# 模拟爬虫返回的嵌套数组(三个子数组长度一致)
name_url_price = [
  ["无线鼠标", "机械键盘", "电竞耳机"],
  ["https://shop.com/mouse", "https://shop.com/keyboard", "https://shop.com/headset"],
  [89.9, 299.9, 399.9]
]

module Catalog
  class Supplies
    attr_accessor :name, :price, :url
    @@all = []

    # 初始化单个商品实例,接收独立的name、url、price
    def initialize(name, url, price)
      @name = name
      @url = url
      @price = price
      @@all << self # 创建实例时自动加入类变量
    end

    # 类方法:批量从嵌套数组创建所有商品实例
    def self.create_from_array(data)
      # 先校验所有子数组长度是否一致,避免数据残缺
      unless data.all? { |arr| arr.length == data[0].length }
        raise ArgumentError, "所有子数组的元素数量必须相同哦"
      end

      # 遍历每个索引,取出对应位置的三个值创建实例
      data[0].each_with_index do |name, index|
        url = data[1][index]
        price = data[2][index]
        new(name, url, price)
      end
    end

    # 对外提供获取所有实例的接口
    def self.all
      @@all.clone # 返回副本,避免外部直接修改类变量数组
    end
  end
end

# 调用批量创建方法
Catalog::Supplies.create_from_array(name_url_price)

# 验证结果
Catalog::Supplies.all.each do |item|
  puts "商品:#{item.name} | 链接:#{item.url} | 价格:#{item.price}"
end

方案优势

  1. 每个商品都是独立实例:再也不会出现同一个对象反复改属性的情况,@@all里的每个元素都是不同的商品实例。
  2. 职责分离:initialize只负责初始化单个实例,create_from_array专门处理批量创建逻辑,代码可读性更强。
  3. 数据校验:提前检查子数组长度是否一致,避免因为爬虫数据异常创建出不完整的商品实例。
  4. 封装类变量:用self.all方法返回@@all的副本,防止外部代码直接修改类变量里的数组,保证数据安全。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 06:55:44