Client LuaCsForBarotrauma
IEnumerableExtensions.cs
1 #nullable enable
2 
3 using System.Collections.Generic;
4 using System;
5 using System.Linq;
6 using System.Collections.Immutable;
7 
9 {
10  public static class IEnumerableExtensions
11  {
15  public static T[] Randomize<T>(this IList<T> source, Rand.RandSync randSync)
16  {
17  return source.OrderBy(i => Rand.Value(randSync)).ToArray();
18  }
19 
23  public static void Shuffle<T>(this IList<T> list, Rand.RandSync randSync)
24  => list.Shuffle(Rand.GetRNG(randSync));
25 
26  public static void Shuffle<T>(this IList<T> list, Random rng)
27  {
28  int n = list.Count;
29  while (n > 1)
30  {
31  n--;
32  int k = rng.Next(n + 1);
33  T value = list[k];
34  list[k] = list[n];
35  list[n] = value;
36  }
37  }
38 
39  public static T? GetRandom<T>(this IReadOnlyList<T> source, Func<T, bool> predicate, Rand.RandSync randSync)
40  {
41  if (predicate == null) { return GetRandom(source, randSync); }
42  return source.Where(predicate).ToArray().GetRandom(randSync);
43  }
44 
54  public static T? GetRandom<T>(this IReadOnlyList<T> source, Rand.RandSync randSync)
55  {
56  int count = source.Count;
57  return count == 0 ? default : source[Rand.Range(0, count, randSync)];
58  }
59 
60  public static T? GetRandom<T>(this IReadOnlyList<T> source, Random random)
61  {
62  int count = source.Count;
63  return count == 0 ? default : source[random.Next(0, count)];
64  }
65 
66  // The reason these "GetRandomUnsynced" methods exist is because
67  // they can be used on all enumerables; GetRandom can only be used
68  // on lists as they can be sorted to guarantee a certain order.
69  public static T? GetRandomUnsynced<T>(this IEnumerable<T> source, Func<T, bool> predicate)
70  {
71  if (predicate == null) { return GetRandomUnsynced(source); }
72  return source.Where(predicate).GetRandomUnsynced();
73  }
74 
75  public static T? GetRandomUnsynced<T>(this IEnumerable<T> source)
76  {
77  if (source is IReadOnlyList<T> list)
78  {
79  return list.GetRandom(Rand.RandSync.Unsynced);
80  }
81  else
82  {
83  int count = source.Count();
84  return count == 0 ? default : source.ElementAt(Rand.Range(0, count, Rand.RandSync.Unsynced));
85  }
86  }
87 
88  public static T? GetRandom<T>(this IEnumerable<T> source, Random rand)
89  where T : PrefabWithUintIdentifier
90  {
91  return source.OrderBy(p => p.UintIdentifier).ToArray().GetRandom(rand);
92  }
93 
94  public static T? GetRandom<T>(this IEnumerable<T> source, Rand.RandSync randSync)
95  where T : PrefabWithUintIdentifier
96  {
97  return source.OrderBy(p => p.UintIdentifier).ToArray().GetRandom(randSync);
98  }
99 
100  public static T? GetRandom<T>(this IEnumerable<T> source, Func<T, bool> predicate, Rand.RandSync randSync)
101  where T : PrefabWithUintIdentifier
102  {
103  return source.Where(predicate).OrderBy(p => p.UintIdentifier).ToArray().GetRandom(randSync);
104  }
105 
106  public static T GetRandomByWeight<T>(this IEnumerable<T> source, Func<T, float> weightSelector, Rand.RandSync randSync)
107  {
108  return ToolBox.SelectWeightedRandom(source, weightSelector, randSync);
109  }
110 
115  public static void ForEachMod<T>(this IEnumerable<T> source, Action<T> action)
116  {
117  if (source.None()) { return; }
118  var temp = new List<T>(source);
119  temp.ForEach(action);
120  }
121 
126  public static void ForEach<T>(this IEnumerable<T> source, Action<T> action)
127  {
128  foreach (var item in source)
129  {
130  action(item);
131  }
132  }
133 
137  public static void Consume<T>(this IEnumerable<T> enumerable)
138  {
139  foreach (var _ in enumerable) { /* do nothing */ }
140  }
141 
145  public static bool None<T>(this IEnumerable<T> source, Func<T, bool>? predicate = null)
146  {
147  if (predicate == null)
148  {
149  return !source.Any();
150  }
151  else
152  {
153  return !source.Any(predicate);
154  }
155  }
156 
157  public static bool Multiple<T>(this IEnumerable<T> source, Func<T, bool>? predicate = null)
158  {
159  if (predicate == null)
160  {
161  return source.Count() > 1;
162  }
163  else
164  {
165  return source.Count(predicate) > 1;
166  }
167  }
168 
169  public static IEnumerable<T> ToEnumerable<T>(this T item)
170  {
171  yield return item;
172  }
173 
174  public static IEnumerable<T> NotNull<T>(this IEnumerable<T?> enumerable) where T : class
175  {
176  foreach (var item in enumerable)
177  {
178  if (item != null)
179  {
180  yield return item;
181  }
182  }
183  }
184 
185  // source: https://stackoverflow.com/questions/19237868/get-all-children-to-one-list-recursive-c-sharp
186  public static IEnumerable<T> SelectManyRecursive<T>(this IEnumerable<T> source, Func<T, IEnumerable<T>> selector)
187  {
188  var result = source.SelectMany(selector);
189  if (!result.Any())
190  {
191  return result;
192  }
193  return result.Concat(result.SelectManyRecursive(selector));
194  }
195 
196  public static void AddIfNotNull<T>(this IList<T> source, T value)
197  {
198  if (value != null) { source.Add(value); }
199  }
200 
201 
202  public static NetCollection<T> ToNetCollection<T>(this IEnumerable<T> enumerable) => new NetCollection<T>(enumerable.ToImmutableArray());
203 
211  public static bool AtLeast<T>(this IEnumerable<T> source, int amount, Predicate<T> predicate)
212  {
213  foreach (T elem in source)
214  {
215  if (predicate(elem)) { amount--; }
216  if (amount <= 0) { return true; }
217  }
218  return false;
219  }
220 
227  public static ICollection<T> CollectionConcat<T>(this IEnumerable<T> self, IEnumerable<T> other)
228  => new CollectionConcat<T>(self, other);
229 
230  public static IReadOnlyList<T> ListConcat<T>(this IEnumerable<T> self, IEnumerable<T> other)
231  => new ListConcat<T>(self, other);
232  }
233 }
Prefab that has a property serves as a deterministic hash of a prefab's identifier....