You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by gg...@apache.org on 2022/07/05 18:13:51 UTC
[commons-lang] branch master updated: Add ArrayUtils.oneHot().
This is an automated email from the ASF dual-hosted git repository.
ggregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-lang.git
The following commit(s) were added to refs/heads/master by this push:
new dad064eeb Add ArrayUtils.oneHot().
dad064eeb is described below
commit dad064eebbde450cb500a0e0d72200c655ac47c6
Author: Gary Gregory <ga...@gmail.com>
AuthorDate: Tue Jul 5 14:02:42 2022 -0400
Add ArrayUtils.oneHot().
---
src/changes/changes.xml | 1 +
.../org/apache/commons/lang3/BooleanUtils.java | 64 ++++++++++-
.../org/apache/commons/lang3/BooleanUtilsTest.java | 119 ++++++++++++++++++++-
3 files changed, 179 insertions(+), 5 deletions(-)
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index b81f2ac9b..26fe8b46e 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -154,6 +154,7 @@ The <action> type attribute can be add,update,fix,remove.
<action type="add" dev="ggregory" due-to="Gary Gregory">Add SystemUtils.IS_JAVA_16.</action>
<action type="add" dev="ggregory" due-to="Gary Gregory">Add SystemUtils.IS_JAVA_17.</action>
<action type="add" dev="ggregory" due-to="Gary Gregory">Add SystemUtils.IS_JAVA_18.</action>
+ <action issue="LANG-1627" type="add" dev="ggregory" due-to="Alberto Scotto, Avijit Chakraborty, Steve Bosman, Bruno P. Kinoshita, Gary Gregory">Add ArrayUtils.oneHot().</action>
<!-- UPDATE -->
<action type="update" dev="ggregory" due-to="Dependabot, XenoAmess, Gary Gregory">Bump actions/cache from 2.1.4 to 3.0.4 #742, #752, #764, #833, #867.</action>
<action type="update" dev="ggregory" due-to="Dependabot">Bump actions/checkout from 2 to 3 #819, #825, #859.</action>
diff --git a/src/main/java/org/apache/commons/lang3/BooleanUtils.java b/src/main/java/org/apache/commons/lang3/BooleanUtils.java
index a33ff893b..bdf967c5d 100644
--- a/src/main/java/org/apache/commons/lang3/BooleanUtils.java
+++ b/src/main/java/org/apache/commons/lang3/BooleanUtils.java
@@ -247,6 +247,54 @@ public class BooleanUtils {
}
return bool.booleanValue() ? Boolean.FALSE : Boolean.TRUE;
}
+ /**
+ * <p>Performs a one-hot on an array of booleans.</p>
+ * <p>
+ * This implementation returns true if one, and only one, of the supplied values is true.
+ * </p>
+ * <p>
+ * See also <a href="https://en.wikipedia.org/wiki/One-hot">One-hot</a>.
+ * </p>
+ * @param array an array of {@code boolean}s
+ * @return the result of the one-hot operations
+ * @throws NullPointerException if {@code array} is {@code null}
+ * @throws IllegalArgumentException if {@code array} is empty.
+ */
+ public static boolean oneHot(final boolean... array) {
+ ObjectUtils.requireNonEmpty(array, "array");
+ boolean result = false;
+ for (boolean element: array) {
+ if (element) {
+ if (result) {
+ return false;
+ }
+ result = element;
+ }
+ }
+ return result;
+ }
+
+ /**
+ * <p>Performs a one-hot on an array of booleans.</p>
+ * <p>
+ * This implementation returns true if one, and only one, of the supplied values is true.
+ * </p>
+ * <p>
+ * Null array elements map to false, like {@code Boolean.parseBoolean(null)} and its callers return false.
+ * </p>
+ * <p>
+ * See also <a href="https://en.wikipedia.org/wiki/One-hot">One-hot</a>.
+ * </p>
+ *
+ * @param array an array of {@code boolean}s
+ * @return the result of the one-hot operations
+ * @throws NullPointerException if {@code array} is {@code null}
+ * @throws IllegalArgumentException if {@code array} is empty.
+ */
+ public static Boolean oneHot(final Boolean... array) {
+ return Boolean.valueOf(oneHot(ArrayUtils.toPrimitive(array)));
+ }
+
/**
* <p>Performs an 'or' operation on a set of booleans.</p>
*
@@ -1075,15 +1123,23 @@ public class BooleanUtils {
/**
* <p>Performs an xor on a set of booleans.</p>
+ * <p>
+ * This behaves like an XOR gate;
+ * it returns true if the number of true values is odd,
+ * and false if the number of true values is zero or even.
+ * </p>
*
* <pre>
- * BooleanUtils.xor(true, true) = false
- * BooleanUtils.xor(false, false) = false
- * BooleanUtils.xor(true, false) = true
+ * BooleanUtils.xor(true, true) = false
+ * BooleanUtils.xor(false, false) = false
+ * BooleanUtils.xor(true, false) = true
+ * BooleanUtils.xor(true, false, false) = true
+ * BooleanUtils.xor(true, true, true) = true
+ * BooleanUtils.xor(true, true, true, true) = false
* </pre>
*
* @param array an array of {@code boolean}s
- * @return the result of the xor operations
+ * @return true if the number of true values in the array is odd; otherwise returns false.
* @throws NullPointerException if {@code array} is {@code null}
* @throws IllegalArgumentException if {@code array} is empty.
*/
diff --git a/src/test/java/org/apache/commons/lang3/BooleanUtilsTest.java b/src/test/java/org/apache/commons/lang3/BooleanUtilsTest.java
index a651b9002..d01579bd5 100644
--- a/src/test/java/org/apache/commons/lang3/BooleanUtilsTest.java
+++ b/src/test/java/org/apache/commons/lang3/BooleanUtilsTest.java
@@ -628,6 +628,124 @@ public class BooleanUtilsTest extends AbstractLangTest {
assertFalse(Modifier.isFinal(BooleanUtils.class.getModifiers()));
}
+ @Test
+ public void testOneHot_object_emptyInput() {
+ assertThrows(IllegalArgumentException.class, () -> BooleanUtils.oneHot(new Boolean[] {}));
+ }
+
+ @Test
+ public void testOneHot_object_nullElementInput() {
+ assertEquals(Boolean.FALSE, BooleanUtils.oneHot(new Boolean[] {null}));
+ }
+
+ @Test
+ public void testOneHot_object_nullInput() {
+ assertThrows(NullPointerException.class, () -> BooleanUtils.oneHot((Boolean[]) null));
+ }
+
+ @Test
+ public void testOneHot_object_validInput_1item() {
+ assertTrue(BooleanUtils.oneHot(new Boolean[]{Boolean.TRUE}), "true");
+
+ assertFalse(BooleanUtils.oneHot(new Boolean[]{Boolean.FALSE}), "false");
+
+ assertFalse(BooleanUtils.oneHot(new Boolean[]{null}), "false");
+ }
+
+ @Test
+ public void testOneHot_object_validInput_2items() {
+ assertFalse(BooleanUtils.oneHot(new Boolean[]{true, true}), "both true");
+
+ assertFalse(BooleanUtils.oneHot(new Boolean[]{false, false}), "both false");
+
+ assertTrue(BooleanUtils.oneHot(new Boolean[]{true, false}), "first true");
+
+ assertTrue(BooleanUtils.oneHot(new Boolean[]{false, true}), "last true");
+ }
+
+ @Test
+ public void testOneHot_object_validInput_2ItemsNullsTreatedAsFalse() {
+ assertFalse(BooleanUtils.oneHot(null, null), "both null");
+
+ assertTrue(BooleanUtils.oneHot(true, null), "first true");
+
+ assertTrue(BooleanUtils.oneHot(null, true), "last true");
+ }
+
+ @Test
+ public void testOneHot_object_validInput_3items() {
+ // none true
+ assertFalse(BooleanUtils.oneHot(new Boolean[]{false, false, false}), "all false");
+
+ // one true
+ assertTrue(BooleanUtils.oneHot(new Boolean[]{true, false, false}), "first true");
+
+ assertTrue(BooleanUtils.oneHot(new Boolean[]{false, true, false}), "middle true");
+
+ assertTrue(BooleanUtils.oneHot(new Boolean[]{false, false, true}), "last true");
+
+ // two true
+ assertFalse(BooleanUtils.oneHot(new Boolean[]{false, true, true}), "first false");
+
+ assertFalse(BooleanUtils.oneHot(new Boolean[]{true, false, true}), "middle false");
+
+ assertFalse(BooleanUtils.oneHot(new Boolean[]{true, true, false}), "last false");
+
+ // three true
+ assertFalse(BooleanUtils.oneHot(new Boolean[]{true, true, true}), "all true");
+ }
+
+ @Test
+ public void testOneHot_primitive_emptyInput() {
+ assertThrows(IllegalArgumentException.class, () -> BooleanUtils.oneHot(new boolean[] {}));
+ }
+
+ @Test
+ public void testOneHot_primitive_nullInput() {
+ assertThrows(NullPointerException.class, () -> BooleanUtils.oneHot((boolean[]) null));
+ }
+
+ @Test
+ public void testOneHot_primitive_validInput_1item() {
+ assertTrue(BooleanUtils.oneHot(new boolean[]{true}), "true");
+
+ assertFalse(BooleanUtils.oneHot(new boolean[]{false}), "false");
+ }
+
+ @Test
+ public void testOneHot_primitive_validInput_2items() {
+ assertFalse(BooleanUtils.oneHot(new boolean[]{true, true}), "both true");
+
+ assertFalse(BooleanUtils.oneHot(new boolean[]{false, false}), "both false");
+
+ assertTrue(BooleanUtils.oneHot(new boolean[]{true, false}), "first true");
+
+ assertTrue(BooleanUtils.oneHot(new boolean[]{false, true}), "last true");
+ }
+
+ @Test
+ public void testOneHot_primitive_validInput_3items() {
+ // none true
+ assertFalse(BooleanUtils.oneHot(new boolean[]{false, false, false}), "all false");
+
+ // one true
+ assertTrue(BooleanUtils.oneHot(new boolean[]{true, false, false}), "first true");
+
+ assertTrue(BooleanUtils.oneHot(new boolean[]{false, true, false}), "middle true");
+
+ assertTrue(BooleanUtils.oneHot(new boolean[]{false, false, true}), "last true");
+
+ // two true
+ assertFalse(BooleanUtils.oneHot(new boolean[]{false, true, true}), "first false");
+
+ assertFalse(BooleanUtils.oneHot(new boolean[]{true, false, true}), "middle false");
+
+ assertFalse(BooleanUtils.oneHot(new boolean[]{true, true, false}), "last false");
+
+ // three true
+ assertFalse(BooleanUtils.oneHot(new boolean[]{true, true, true}), "all true");
+ }
+
@Test
public void testOr_object_emptyInput() {
assertThrows(IllegalArgumentException.class, () -> BooleanUtils.or(new Boolean[] {}));
@@ -1034,5 +1152,4 @@ public class BooleanUtilsTest extends AbstractLangTest {
BooleanUtils.xor(new boolean[] { true, true, true }),
"true ^ true ^ true");
}
-
}