R语言将矩阵存入列表时所有矩阵元素始终相同的问题
问题描述
编写R代码复刻Yahtzee(快艇骰子)游戏时,预先创建10行5列的矩阵,计划将每次掷骰子的结果写入矩阵对应行,再逐次将当前状态的矩阵存入列表。实际运行后发现,列表内存储的所有矩阵元素完全一致,无法实现每个矩阵对应不同掷骰阶段数值的预期效果。
问题复现代码:
matriz <- matrix(1:5, nrow = 10, ncol = 5) listas <- list() rolar <- function() { dados <- 1:6 dados <- replicate(1, sample(dados, size = 1,replace = TRUE)) return(dados) } for (i in 1:10) { matriz[i, ] <- rolar() listas[[i]] <- matriz print(listas[i]) } str(listas)
问题原因
- 掷骰子函数逻辑错误:
rolar()每次仅返回1个1-6的随机数,赋值给矩阵整行时R会自动循环补全为5个相同值,不符合Yahtzee一次掷5个独立骰子的规则。 - 核心问题是R的修改时拷贝(copy-on-modify)机制:循环中每次将全局环境的
matriz赋值给列表元素时,没有触发实际的内存拷贝,列表所有元素都指向同一个matriz对象的内存地址。后续循环修改matriz的行值时,列表中所有指向该地址的元素都会同步更新,最终循环结束后所有列表元素都是最后一次修改完成的矩阵状态。 - 附加细节问题:原代码打印时用
listas[i]取到的是长度为1的子列表,不是矩阵本身,输出格式不符合调试预期。
修复方案
- 修正掷骰子函数,一次返回5个独立的1-6随机数,匹配单轮掷5个骰子的逻辑。
- 每次向列表存入矩阵时,显式创建矩阵副本,切断和全局
matriz对象的绑定,强制触发值拷贝。 - 调整列表取值写法,打印时直接取矩阵元素而非子列表。
修复后可运行代码:
listas <- list() # 修正掷骰子函数:一次返回5个骰子的独立结果 rolar <- function() { sample(1:6, size = 5, replace = TRUE) } # 初始化空矩阵逐行存储掷骰结果 current_mat <- matrix(nrow = 0, ncol = 5) for (i in 1:10) { # 新增本轮掷骰结果到矩阵 current_mat <- rbind(current_mat, rolar()) # 显式创建副本存入列表,触发值拷贝 listas[[i]] <- as.matrix(current_mat) # 正确打印矩阵元素 print(listas[[i]]) } str(listas)
如果需要保留预先创建10行矩阵的写法,只需要在存入列表时显式生成副本即可,比如将listas[[i]] <- matriz替换为listas[[i]] <- matrix(matriz, nrow = 10, ncol = 5),同时修正rolar函数的返回值长度。
内容的提问来源于stack exchange,提问作者Caio Katarn
相关产品推荐
相关产品推荐

