gpt4 book ai didi

c# - 反转嵌套 Observable 的顺序

转载 作者:太空狗 更新时间:2023-10-30 01:35:04 25 4
gpt4 key购买 nike

我想交换一对嵌套 IObservables 的顺序,对其发生的方式有一些限制。

作为一个具体的(尽管有点人为的)示例,假设有一个游戏服务器托管连续的在线多人游戏。玩家可以随时加入并在每个游戏中执行操作。以下类具有工作实现,可提供玩家在连续游戏中执行的操作的只读 View :

class GameServer
{
public IObservable<Game> Games { get { ... } }
}

class Game
{
public int GameId { get { ... } }
public IObservable<GamePlayer> Players { get { ... } }
}

class GamePlayer
{
public int PlayerId { get { ... } }
public IObservable<PlayerAction> PlayerActions { get { ... } }
}

在这些类中,有一个嵌套的可观察对象 IObservable<IObservable<IObservable<PlayerAction>>> .这是提供以下形式的信息:There are a series of games. Within each game a series of players joined. Each player performed a number of actions in the game .

我想做的是重新排列这些数据,以便它提供以下信息:There are a number of players. Since each player joined, a series of games have been played. Within each game, the player performed a number of actions.这看起来像是以下方法的实现:

IObservable<Player> Players { get; }

使用以下类:

class Player
{
public Player(int playerId, IObservable<PlayerGame> games)
{
PlayerId = playerId;
Games = games;
}

public int PlayerId { get; private set; }
public IObservable<PlayerGame> Games { get; private set; }
}

class PlayerGame
{
public PlayerGame(int gameId, IObservable<PlayerAction> gameActions)
{
GameId = gameId;
GameActions = gameActions;
}

public int GameId { get; private set; }
public IObservable<PlayerAction> GameActions { get; private set; }
}

与其提供一系列游戏并显示每个游戏中每个玩家所做的事情,不如提供一系列游戏并显示每个玩家在连续游戏中的参与情况。

还有一个额外的要求:玩家加入后,他们在每一场连续游戏中的行为都应该显示出来,无论他们在游戏中是否做了任何事情(即,如果玩家在游戏中什么都不做,Player 仍应在游戏开始时推送一个新的 PlayerGame,即使其 GameActions 从未推送任何值)。

我将如何实现 Players使用 GameServer.Games作为相关数据的来源?

(回应 DaveSexton 的评论:ID 代表什么、数据来自何处以及程序在什么框架或环境中运行并不重要。所有必需的数据都在 GameServer 中, GameGamePlayer 类。我只是不知道如何将其改组为 Player 形式。)

一个几乎可行的解决方案

为了更好地了解我的目标,这里有一个几乎可行的解决方案。唯一的问题是如果新游戏开始并且GameServer.Games推出新的 Game , Player.Games不会相应地推送一个新的 PlayerGame对于每个现有玩家(我希望如此)。

Players = gameServer.Games
.Select(g => g.Players.Select(p => new { g.GameId, p.PlayerId, p.PlayerActions }))
.Switch()
.GroupBy(t => t.PlayerId)
.Select(
group =>
new Player(group.Key, group.Select(t => new PlayerGame(t.GameId, t.PlayerActions))));

最佳答案

更新的答案基于 OP 提供的新信息和示例查询。

Players  = Games.Publish(publishedGames => 
from game in publishedGames
from player in game.Players
select new Player(
player.PlayerId,
(from game2 in publishedGames
from player2 in game2.Players
where player2.PlayerId == player.PlayerId
select new PlayerGame(game2.GameId, player2.PlayerActions))
.StartWith(new PlayerGame(game.GameId, player.PlayerActions))))
.Distinct(player => player.PlayerId)

这实际上只是一个 SelectMany 查询。对于每个 Game,对于每个 GamePlayer,它都会投影一个新的 Player

最初的问题是如何从 GamePlayer 创建一个新的 Player。您在示例查询中显示的是,您只想将 PlayerGame 对象从 Game 对象转换;因此,我刚刚使用了一个内部查询来过滤具有玩家 ID 的游戏。就是这样。

Publish 仅在 Games 的情况下使用。如果它很热门,那么您就不需要Publish

我添加了 Distinct,因为如果没有它,每当观察到已经观察过的玩家的 Game 时,这些玩家就会再次被观察到。

关于c# - 反转嵌套 Observable 的顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27489072/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com