gpt4 book ai didi

c# - 从 C# 中的加权列表中选择 x 个随机元素(无需替换)

转载 作者:太空狗 更新时间:2023-10-29 21:40:38 24 4
gpt4 key购买 nike

更新:我的问题已经解决,我更新了问题中的代码源以与 Jason 的回答相匹配。请注意,rikitikitik 答案是解决从样本中抽取卡片并进行替换的问题。

我想从加权列表中选择 x 个随机元素。抽样是没有更换的。我找到了这个答案:https://stackoverflow.com/a/2149533/57369用 Python 实现。我用 C# 实现并测试了它。但结果(如下所述)与我的预期不符。我不了解 Python,所以我很确定我在将代码移植到 C# 时犯了一个错误,但我看不到 Pythong 中的代码在哪里有很好的文档记录。

我选择一张卡片 10000 次,这是我获得的结果(结果在执行过程中是一致的):

Card 1: 18.25 % (10.00 % expected)
Card 2: 26.85 % (30.00 % expected)
Card 3: 46.22 % (50.00 % expected)
Card 4: 8.68 % (10.00 % expected)

如您所见,卡片 1 和卡片 4 的权重均为 1,但卡片 1 的选择频率远高于卡片 4(即使我选择了 2 或 3 张卡片)。

测试数据:

var cards = new List<Card>
{
new Card { Id = 1, AttributionRate = 1 }, // 10 %
new Card { Id = 2, AttributionRate = 3 }, // 30 %
new Card { Id = 3, AttributionRate = 5 }, // 50 %
new Card { Id = 4, AttributionRate = 1 }, // 10 %
};

这是我在 C# 中的实现

public class CardAttributor : ICardsAttributor
{
private static Random random = new Random();

private List<Node> GenerateHeap(List<Card> cards)
{
List<Node> nodes = new List<Node>();
nodes.Add(null);

foreach (Card card in cards)
{
nodes.Add(new Node(card.AttributionRate, card, card.AttributionRate));
}

for (int i = nodes.Count - 1; i > 1; i--)
{
nodes[i>>1].TotalWeight += nodes[i].TotalWeight;
}

return nodes;
}

private Card PopFromHeap(List<Node> heap)
{
Card card = null;

int gas = random.Next(heap[1].TotalWeight);
int i = 1;

while (gas >= heap[i].Weight)
{
gas -= heap[i].Weight;
i <<= 1;

if (gas >= heap[i].TotalWeight)
{
gas -= heap[i].TotalWeight;
i += 1;
}
}

int weight = heap[i].Weight;
card = heap[i].Value;

heap[i].Weight = 0;

while (i > 0)
{
heap[i].TotalWeight -= weight;
i >>= 1;
}

return card;
}

public List<Card> PickMultipleCards(List<Card> cards, int cardsToPickCount)
{
List<Card> pickedCards = new List<Card>();

List<Node> heap = GenerateHeap(cards);

for (int i = 0; i < cardsToPickCount; i++)
{
pickedCards.Add(PopFromHeap(heap));
}

return pickedCards;
}
}

class Node
{
public int Weight { get; set; }
public Card Value { get; set; }
public int TotalWeight { get; set; }

public Node(int weight, Card value, int totalWeight)
{
Weight = weight;
Value = value;
TotalWeight = totalWeight;
}
}

public class Card
{
public int Id { get; set; }
public int AttributionRate { get; set; }
}

最佳答案

程序中有两个小错误。首先,随机数的范围应该正好等于所有元素的总重量:

int gas = random.Next(heap[1].TotalWeight);

其次,将显示 gas > 的两个地方都改为 gas >=

(原来的Python代码是可以的,因为gas是一个 float ,所以>>=的区别可以忽略不计. 该代码被编写为接受整数或浮点权重。)

更新:好的,您在代码中进行了建议的更改。我认为该代码现在是正确的!

关于c# - 从 C# 中的加权列表中选择 x 个随机元素(无需替换),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11775946/

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