Last active
January 30, 2019 05:37
-
-
Save Lachee/6f1cc8885fb6e1001addb7adb055d065 to your computer and use it in GitHub Desktop.
Randomised List
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections; | |
using System.Collections.Generic; | |
using UnityEngine; | |
namespace Lachee.Collections | |
{ | |
/// <summary> | |
/// A randomised list. It will store a collection of values with specified weights and provide functionallity to select randomly from the list. | |
/// </summary> | |
/// <typeparam name="T">Type to store as the value.</typeparam> | |
public class Rist<T> : IEnumerable<WeightValuePair<T>> | |
{ | |
private List<WeightValuePair<T>> _list; | |
private float _weight = 0; | |
/// <summary> | |
/// Number of elements currently in the table | |
/// </summary> | |
public int Count { get { return _list.Count; } } | |
/// <summary> | |
/// The total tally of the weights. Use RecalculateWeights(); to update this value. | |
/// </summary> | |
public float Weight { get { return _weight; } } | |
public Rist() { _list = new List<WeightValuePair<T>>(); } | |
public Rist(int capacity) { _list = new List<WeightValuePair<T>>(capacity); } | |
public Rist(List<WeightValuePair<T>> vwp) | |
{ | |
_list = vwp; | |
foreach (var wp in vwp) _weight += wp.Weight; | |
} | |
/// <summary> | |
/// Clears the random table. | |
/// </summary> | |
public void Clear() | |
{ | |
_list.Clear(); | |
_weight = 0; | |
} | |
/// <summary> | |
/// Adds a new item with a specified weight to the table and increments the total weight. | |
/// </summary> | |
/// <param name="item">Item to add</param> | |
/// <param name="weight">WEight this item has</param> | |
public void Add(T item, float weight) | |
{ | |
Add(new WeightValuePair<T>() { Value = item, Weight = weight }); | |
} | |
/// <summary> | |
/// Adds a new value weight pair to the table and increments the total weight. | |
/// </summary> | |
/// <param name="pair">The item to be added</param> | |
public void Add(WeightValuePair<T> pair) | |
{ | |
//We don't want to add anything that has no chance at all. | |
//if (pair.Weight <= 0) return; | |
_list.Add(pair); | |
_weight += pair.Weight; | |
} | |
/// <summary> | |
/// Attempts to pick a random element from the table based of weighting. | |
/// </summary> | |
/// <param name="random">A random value between 0 and 1. This is done so System.Random or Unity.Random can be used.</param> | |
/// <param name="result">The random element that was fetched.</param> | |
/// <returns>false if we are unable to find a random element.</returns> | |
public bool Randomise(float random, out WeightValuePair<T> result) | |
{ | |
float rand = random * Weight; | |
for (int i = 0; i < _list.Count; i++) | |
{ | |
rand -= _list[i].Weight; | |
if (rand < 0) | |
{ | |
result = _list[i]; | |
return true; | |
} | |
} | |
result = default(WeightValuePair<T>); | |
return false; | |
} | |
/// <summary> | |
/// Attempts to pick a random element from the table based of weighting. | |
/// </summary> | |
/// <param name="random">A random value between 0 and 1. This is done so System.Random or Unity.Random can be used.</param> | |
/// <param name="item">The random element that was fetched.</param> | |
/// <returns>false if we are unable to find a random element.</returns> | |
public bool Randomise(float random, out T item) | |
{ | |
WeightValuePair<T> result; | |
if (!Randomise(random, out result)) | |
{ | |
item = default(T); | |
return false; | |
} | |
item = result.Value; | |
return true; | |
} | |
/// <summary> | |
/// Recalculates the total weights | |
/// </summary> | |
public void RecalculateWeights() | |
{ | |
_weight = 0; | |
for (int i = 0; i < _list.Count; i++) | |
_weight += _list[i].Weight; | |
} | |
public IEnumerator<WeightValuePair<T>> GetEnumerator() | |
{ | |
return _list.GetEnumerator(); | |
} | |
IEnumerator IEnumerable.GetEnumerator() | |
{ | |
return (IEnumerator)GetEnumerator(); | |
} | |
} | |
public struct WeightValuePair<T> | |
{ | |
public T Value { get; set; } | |
public float Weight { get; set; } | |
public WeightValuePair(T value, float weight) | |
{ | |
Value = value; | |
Weight = weight; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment