XDracam / unity-corelibrary

Collection of classes and extension methods that make life with Unity3D more comfortable
MIT License
15 stars 3 forks source link

WeightedShuffled #54

Open Eregerog opened 4 years ago

Eregerog commented 4 years ago

We alrady have IEnumerable.Shuffled, why not provide a WeightedShuffled: public static IEnumerable<T> WeightedShuffled(this IEnumerable<(T item, float weight)> source){...} I've already implemented something like this for another project, which only works weights > 0 (without safety checks):

public static IEnumerable<T> WeightedShuffled<T>(this IEnumerable<(T item, float weight)> source)
        {
            var remaining = source.ToList();
            var result = new List<T>();

            while (remaining.IsNotEmpty())
            {
                var sum = remaining.Select(tuple => tuple.weight).Sum();
                var rand = Random.Range(0f, sum);

                var currentIndex = 0;
                while (currentIndex < remaining.Count - 1 && rand > remaining[currentIndex].weight)
                {
                    rand -= remaining[currentIndex].weight;
                    ++currentIndex;
                }

                result.Add(remaining[currentIndex].item);
                remaining.RemoveAt(currentIndex);
            }

            return result;
        }
XDracam commented 4 years ago

The idea of adding a weighted shuffle is great. However, I'd rather use an established algorithm for this problem. Further research is required here.