在 R 中 return 多个修改参数的最佳方式?
Best way to return multiple modified arguments in R?
我正在尝试编写一个函数(或最好的 R 替代方案),给定一个 deck 向量和一个 hand 向量,从牌组中取出第一个元素并将其添加到手上。
# initialize the deck. We don't care about suits, so modulus 13
deck <- sample(52, 52, replace = FALSE, prob = NULL) %% 13 + 1
# initilize the hand
hand <- vector(mode="numeric", length=0)
#deal a card from the deck to the hand.
# it's these two lines I'd like to put in something like a function
# and return the modified vectors
phand <- c(hand, deck[1])
deck <- deck[-1]
在类似 Python 的情况下,您可以这样做:
def dealcard(deck,hand)
# do something to deck and hand
return deck, hand
deck,hand = dealcard(deck,hand)
查看第一个答案:
modify variable within R function
There are ways as @Dason showed, but really - you shouldn't!
The whole paradigm of R is to "pass by value". @Rory just posted the normal way to handle it - just return the modified value...
那么什么是最 R-thonic 实现此 "modifying multiple arguments to a function" 的方法?
我可以看到用一个矩阵完成类似的事情,其中一列使用数字来指示 row/card 发给哪只手,但这会使代码不那么直观。很容易想象一个函数:
score <- ScoreFunction(DealerHand)
对比:
score <- ScoreFunction(DeckMatrix, 1)
简答
您可以从您的函数中 return list。
简单示例
dealcard <- function(deck, hand) {
# There needs to be a card to deal
stopifnot(length(deck) > 0)
# Add the card from the top of the deck to the hand
hand <- c(hand, deck[1])
# Remove the card from the deck
deck <- deck[-1]
# Create a named list from the modified inputs
output <- list(deck=deck, hand=hand)
return(output)
}
但请注意,这种方法实际上并没有修改全局环境中的 deck
和 hand
对象。 (你 可以 使用 <<-
做到这一点,但在大多数情况下你不应该这样做。)所以你可以这样做:
# Initialize deck and hand as a list
# Full deck, empty hand
deck.hand <- list(deck=sample(52, 52, replace=FALSE), hand=NULL)
# Deal a card
deck.hand <- with(deck.hand, dealcard(deck, hand))
现在,如果您查看 deck.hand
,您会看到 deck
和 hand
项已适当更新。
更多的例子
当同一个列表中有多个玩家时,这可以很容易地扩展到与特定玩家交易。
# Initialize the game
# Three players, everyone starts with empty hands
game <- list(deck=sample(52, 52, replace=FALSE) %% 13 + 1,
dealer=NULL, sally=NULL, john=NULL)
dealcard <- function(game, player, deck="deck") {
# Make sure the player specified is in the game
stopifnot(player %in% names(game) && deck %in% names(game))
# There needs to be a card to deal
stopifnot(length(game[[deck]]) > 0)
# Give the next card to the specified player
game[[player]] <- c(game[[player]], game[[deck]][1])
# Remove the card from the deck
game[[deck]] <- game[[deck]][-1]
# Return the new state of the game
return(game)
}
# Give everyone a card
game <- dealcard(game, "dealer")
game <- dealcard(game, "sally")
game <- dealcard(game, "john")
这使用语法 list[["itemname"]]
。列表项作为 字符串 传递。这相当于使用 $
提取项目,即 list$itemname
.
这里我们传入整个列表,只修改其中必要的部分,然后 returning 整个修改后的列表。将原始列表设置为等于 returned 值就像就地修改列表一样。
现在,如果您查看 game
的内容,每个玩家将拥有一张牌,并且牌组将缺少已分发的牌。
有趣的扩展
我也有点喜欢这个。
想给每位玩家连续发五张牌吗?
players <- names(game)[names(game) != "deck"]
for (i in 1:5) {
for (player in players) {
game <- dealcard(game, player)
}
}
再看看game
。每个玩家有 5 张牌,由于循环是以这种方式构建的,因此发牌顺序模仿了标准纸牌游戏。
您可以 return 通过使用 "deck"
作为玩家和玩家作为牌组来将一张牌加入牌组,如下所示:
# John returns his first card to the deck
game <- dealcard(game, player="deck", deck="john")
给定一手牌以某种方式计分的函数,您可以轻松获得每个玩家的分数。
# Example scoring
scorehand <- function(game, player) {
return(sum(game[[player]]))
}
sapply(players, scorehand, game=game)
这将通过将 scorehand()
函数应用于向量 players
的每个元素来显示每个玩家的当前分数,向量 players
由玩家的名字组成。
TL;DR
使用列表。
我正在尝试编写一个函数(或最好的 R 替代方案),给定一个 deck 向量和一个 hand 向量,从牌组中取出第一个元素并将其添加到手上。
# initialize the deck. We don't care about suits, so modulus 13
deck <- sample(52, 52, replace = FALSE, prob = NULL) %% 13 + 1
# initilize the hand
hand <- vector(mode="numeric", length=0)
#deal a card from the deck to the hand.
# it's these two lines I'd like to put in something like a function
# and return the modified vectors
phand <- c(hand, deck[1])
deck <- deck[-1]
在类似 Python 的情况下,您可以这样做:
def dealcard(deck,hand)
# do something to deck and hand
return deck, hand
deck,hand = dealcard(deck,hand)
查看第一个答案: modify variable within R function
There are ways as @Dason showed, but really - you shouldn't!
The whole paradigm of R is to "pass by value". @Rory just posted the normal way to handle it - just return the modified value...
那么什么是最 R-thonic 实现此 "modifying multiple arguments to a function" 的方法?
我可以看到用一个矩阵完成类似的事情,其中一列使用数字来指示 row/card 发给哪只手,但这会使代码不那么直观。很容易想象一个函数:
score <- ScoreFunction(DealerHand)
对比:
score <- ScoreFunction(DeckMatrix, 1)
简答
您可以从您的函数中 return list。
简单示例
dealcard <- function(deck, hand) {
# There needs to be a card to deal
stopifnot(length(deck) > 0)
# Add the card from the top of the deck to the hand
hand <- c(hand, deck[1])
# Remove the card from the deck
deck <- deck[-1]
# Create a named list from the modified inputs
output <- list(deck=deck, hand=hand)
return(output)
}
但请注意,这种方法实际上并没有修改全局环境中的 deck
和 hand
对象。 (你 可以 使用 <<-
做到这一点,但在大多数情况下你不应该这样做。)所以你可以这样做:
# Initialize deck and hand as a list
# Full deck, empty hand
deck.hand <- list(deck=sample(52, 52, replace=FALSE), hand=NULL)
# Deal a card
deck.hand <- with(deck.hand, dealcard(deck, hand))
现在,如果您查看 deck.hand
,您会看到 deck
和 hand
项已适当更新。
更多的例子
当同一个列表中有多个玩家时,这可以很容易地扩展到与特定玩家交易。
# Initialize the game
# Three players, everyone starts with empty hands
game <- list(deck=sample(52, 52, replace=FALSE) %% 13 + 1,
dealer=NULL, sally=NULL, john=NULL)
dealcard <- function(game, player, deck="deck") {
# Make sure the player specified is in the game
stopifnot(player %in% names(game) && deck %in% names(game))
# There needs to be a card to deal
stopifnot(length(game[[deck]]) > 0)
# Give the next card to the specified player
game[[player]] <- c(game[[player]], game[[deck]][1])
# Remove the card from the deck
game[[deck]] <- game[[deck]][-1]
# Return the new state of the game
return(game)
}
# Give everyone a card
game <- dealcard(game, "dealer")
game <- dealcard(game, "sally")
game <- dealcard(game, "john")
这使用语法 list[["itemname"]]
。列表项作为 字符串 传递。这相当于使用 $
提取项目,即 list$itemname
.
这里我们传入整个列表,只修改其中必要的部分,然后 returning 整个修改后的列表。将原始列表设置为等于 returned 值就像就地修改列表一样。
现在,如果您查看 game
的内容,每个玩家将拥有一张牌,并且牌组将缺少已分发的牌。
有趣的扩展
我也有点喜欢这个。
想给每位玩家连续发五张牌吗?
players <- names(game)[names(game) != "deck"]
for (i in 1:5) {
for (player in players) {
game <- dealcard(game, player)
}
}
再看看game
。每个玩家有 5 张牌,由于循环是以这种方式构建的,因此发牌顺序模仿了标准纸牌游戏。
您可以 return 通过使用 "deck"
作为玩家和玩家作为牌组来将一张牌加入牌组,如下所示:
# John returns his first card to the deck
game <- dealcard(game, player="deck", deck="john")
给定一手牌以某种方式计分的函数,您可以轻松获得每个玩家的分数。
# Example scoring
scorehand <- function(game, player) {
return(sum(game[[player]]))
}
sapply(players, scorehand, game=game)
这将通过将 scorehand()
函数应用于向量 players
的每个元素来显示每个玩家的当前分数,向量 players
由玩家的名字组成。
TL;DR
使用列表。