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

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的子列表,不是矩阵本身,输出格式不符合调试预期。
修复方案
  1. 修正掷骰子函数,一次返回5个独立的1-6随机数,匹配单轮掷5个骰子的逻辑。
  2. 每次向列表存入矩阵时,显式创建矩阵副本,切断和全局matriz对象的绑定,强制触发值拷贝。
  3. 调整列表取值写法,打印时直接取矩阵元素而非子列表。

修复后可运行代码:

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.01 21:01:02