diff --git a/src/BizHawk.Common/Extensions/CollectionExtensions.cs b/src/BizHawk.Common/Extensions/CollectionExtensions.cs
index ff80ee2192..39f0303ef9 100644
--- a/src/BizHawk.Common/Extensions/CollectionExtensions.cs
+++ b/src/BizHawk.Common/Extensions/CollectionExtensions.cs
@@ -490,6 +490,42 @@ namespace BizHawk.Common.CollectionExtensions
return removed;
}
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static bool? Unanimity(this IEnumerable lazy)
+ => lazy is IReadOnlyCollection collection
+ ? Unanimity(collection)
+ : Unanimity(lazy as ISet ?? lazy.ToHashSet());
+
+ ///
+ public static bool? Unanimity(this IReadOnlyCollection collection)
+ {
+ if (collection is bool[] arr) return Unanimity(arr.AsSpan());
+ if (collection is List list)
+ {
+ return list is [ var first, .. ] && list.IndexOf(!first, index: 1) < 0 ? first : null;
+ }
+ var iter = collection.GetEnumerator();
+ if (!iter.MoveNext()) return null;
+ var first1 = iter.Current;
+ while (iter.MoveNext()) if (iter.Current != first1) return null;
+ return first1;
+ }
+
+ ///
+ /// if all ,
+ /// if all ,
+ /// if mixed (or empty)
+ ///
+ public static bool? Unanimity(this ISet set)
+ => set.Contains(false)
+ ? set.Contains(true) ? null : false
+ : set.Contains(true) ? true : null;
+
+ ///
+ public static bool? Unanimity(this ReadOnlySpan span)
+ => span is [ var first, .. ] && !span.Slice(start: 1).Contains(!first) ? first : null;
+
public static bool IsSortedAsc(this IReadOnlyList list)
where T : IComparable
{
diff --git a/src/BizHawk.Tests/Common/CollectionExtensions/CollectionExtensionTests.cs b/src/BizHawk.Tests/Common/CollectionExtensions/CollectionExtensionTests.cs
index 83fb2494de..156aa227ff 100644
--- a/src/BizHawk.Tests/Common/CollectionExtensions/CollectionExtensionTests.cs
+++ b/src/BizHawk.Tests/Common/CollectionExtensions/CollectionExtensionTests.cs
@@ -1,5 +1,7 @@
using System.Collections;
using System.Collections.Generic;
+using System.Collections.Immutable;
+using System.Linq;
using BizHawk.Common.CollectionExtensions;
@@ -134,5 +136,21 @@ namespace BizHawk.Tests.Common.CollectionExtensions
c.RemoveAll(Predicate);
Assert.AreEqual(2, c.Count, nameof(CE.RemoveAll) + " failed on (ICollection not IList)");
}
+
+ [DataRow(new bool[0], null)]
+ [DataRow(new bool[] { true }, true)]
+ [DataRow(new bool[] { false }, false)]
+ [DataRow(new bool[] { true, true }, true)]
+ [DataRow(new bool[] { false, false }, false)]
+ [DataRow(new bool[] { true, false }, null)]
+ [DataRow(new bool[] { false, true }, null)]
+ [TestMethod]
+ public void TestUnanimity(bool[] array, bool? expected)
+ {
+ Assert.AreEqual(expected, ((ISet) array.ToHashSet()).Unanimity(), "ISet");
+ Assert.AreEqual(expected, array.Unanimity(), "Span");
+ Assert.AreEqual(expected, array.ToList().Unanimity(), "List");
+ Assert.AreEqual(expected, ImmutableArray.Create(array).Unanimity(), "IROColl not List");
+ }
}
}