/ 猿问

# 随机加权选择

2019-12-21 13:06:38

public class Broker

{

public string Name = string.Empty;

public int Weight = 0;

public Broker(string n, int w)

{

this.Name = n;

this.Weight = w;

}

}

class Program

{

private static Random _rnd = new Random();

public static Broker GetBroker(List<Broker> brokers, int totalWeight)

{

// totalWeight is the sum of all brokers' weight

int randomNumber = _rnd.Next(0, totalWeight);

Broker selectedBroker = null;

foreach (Broker broker in brokers)

{

if (randomNumber <= broker.Weight)

{

selectedBroker = broker;

break;

}

randomNumber = randomNumber - broker.Weight;

}

return selectedBroker;

}

static void Main(string[] args)

{

List<Broker> brokers = new List<Broker>();

brokers.Add(new Broker("A", 10));

brokers.Add(new Broker("B", 20));

brokers.Add(new Broker("C", 20));

brokers.Add(new Broker("D", 10));

// total the weigth

int totalWeight = 0;

foreach (Broker broker in brokers)

{

totalWeight += broker.Weight;

}

while (true)

{

Dictionary<string, int> result = new Dictionary<string, int>();

Broker selectedBroker = null;

for (int i = 0; i < 1000; i++)

{

selectedBroker = GetBroker(brokers, totalWeight);

if (selectedBroker != null)

{

if (result.ContainsKey(selectedBroker.Name))

{

result[selectedBroker.Name] = result[selectedBroker.Name] + 1;

}

## 4 回答

if (randomNumber < broker.Weight)

aluckdog

using System;

using System.Linq;

using System.Collections;

using System.Collections.Generic;

public static class IEnumerableExtensions {

public static T RandomElementByWeight<T>(this IEnumerable<T> sequence, Func<T, float> weightSelector) {

float totalWeight = sequence.Sum(weightSelector);

// The weight we are after...

float itemWeightIndex =  new Random().NextDouble() * totalWeight;

float currentWeightIndex = 0;

foreach(var item in from weightedItem in sequence select new { Value = weightedItem, Weight = weightSelector(weightedItem) }) {

currentWeightIndex += item.Weight;

// If we've hit or passed the weight we are after for this item then it's the one we want....

if(currentWeightIndex >= itemWeightIndex)

return item.Value;

}

return default(T);

}

}

Dictionary<string, float> foo = new Dictionary<string, float>();

foo.Add("Item 25% 1", 0.5f);

foo.Add("Item 25% 2", 0.5f);

foo.Add("Item 50%", 1f);

for(int i = 0; i < 10; i++)

Console.WriteLine(this, "Item Chosen {0}", foo.RandomElementByWeight(e => e.Value));

class Program

{

static void Main(string[] args)

{

var books = new List<Book> {

new Book{Isbn=1,Name="A",Weight=1},

new Book{Isbn=2,Name="B",Weight=100},

new Book{Isbn=3,Name="C",Weight=1000},

new Book{Isbn=4,Name="D",Weight=10000},

new Book{Isbn=5,Name="E",Weight=100000}};

Book randomlySelectedBook = WeightedRandomization.Choose(books);

}

}

public static class WeightedRandomization

{

public static T Choose<T>(List<T> list) where T : IWeighted

{

if (list.Count == 0)

{

return default(T);

}

int totalweight = list.Sum(c => c.Weight);

Random rand = new Random();

int choice = rand.Next(totalweight);

int sum = 0;

foreach (var obj in list)

{

for (int i = sum; i < obj.Weight + sum; i++)

{

if (i >= choice)

{

return obj;

}

}

sum += obj.Weight;

}

return list.First();

}

}

public interface IWeighted

{

int Weight { get; set; }

}

public class Book : IWeighted

{

public int Isbn { get; set; }

public string Name { get; set; }

public int Weight { get; set; }

}

IWeightedRandomizer<string> randomizer = new DynamicWeightedRandomizer<string>();

randomizer["Joe"] = 1;

randomizer["Ryan"] = 2;

randomizer["Jason"] = 2;

string name1 = randomizer.RandomWithReplacement();

//name1 has a 20% chance of being "Joe", 40% of "Ryan", 40% of "Jason"

string name2 = randomizer.RandomWithRemoval();

//Same as above, except whichever one was chosen has been removed from the list.

• 4 回答
• 0 关注
• 58 浏览

0/150