r - 在 R 中返回多个修改参数的最佳方法?

标签 r function arguments multiple-value

我正在尝试编写一个函数(或最好的 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方法是什么?

我可以看到使用矩阵完成类似的事情,其中​​一列使用数字来指示行/牌发给哪只手,但这会使代码不太直观。很容易想象一个函数:

score <- ScoreFunction(DealerHand)

对比:

score <- ScoreFunction(DeckMatrix, 1)

最佳答案

简短回答

您可以返回 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)
}

但请注意,这种方法实际上并没有修改 deckhand全局环境中的对象。 (您可以使用 <<- 来做到这一点,但在大多数情况下您不应该这样做。)因此您可以这样做:

# 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 ,您会看到 deckhand项目已适当更新。

更多涉及的示例

当同一列表中有多个玩家时,可以轻松扩展以处理特定玩家。

# 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 .

这里我们传入整个列表,仅修改其中必要的部分,然后返回整个修改后的列表。将原始列表设置为等于返回值就像就地修改列表一样。

现在,如果您查看 game 的内容,每个玩家将拥有一张牌,而牌组中将缺少已分发的牌。

有趣的扩展

我对此有点太投入了。

想要连续向每位玩家发五张牌?

players <- names(game)[names(game) != "deck"]

for (i in 1:5) {
    for (player in players) {
        game <- dealcard(game, player)
    }
}

看看game再次。每个玩家有 5 张牌,由于循环是这样构建的,因此发牌顺序模仿了标准纸牌游戏的顺序。

您可以使用 "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 的函数,由玩家姓名组成。

TL;DR

使用列表。

关于r - 在 R 中返回多个修改参数的最佳方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29661348/

相关文章:

javascript - 当用户超过40岁时如何返回true

command-line - 从 DrRacket 读取命令行参数

具有多个隐式参数的函数文字

r - 检查 R 中变量值 (v) 的前一个/连续数字

r - 从源安装 Shiny 服务器时找不到模块 '../package'

r - 将 GLM 的公式设置为 R 中列的总和

c - 以错误的方式调用函数(序列的总和)

r - 在 RStudio 中从源代码安装 R 包时出现问题 - Ubuntu 16.04

c - 将整个数组作为参数传递给函数

function - 为什么Powershell认为我要返回一个object []而不是DataTable?