Skip to content
This repository has been archived by the owner on Feb 18, 2024. It is now read-only.

Commit

Permalink
Fix any/all for Kleene logic (#1545)
Browse files Browse the repository at this point in the history
  • Loading branch information
stinodego authored Aug 19, 2023
1 parent c1446fb commit 5720d9a
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 20 deletions.
42 changes: 38 additions & 4 deletions src/compute/boolean.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,24 +230,58 @@ pub fn or_scalar(array: &BooleanArray, scalar: &BooleanScalar) -> BooleanArray {
}
}

/// Returns whether any of the values in the array is `true`
/// Returns whether any of the values in the array are `true`.
///
/// Null values are ignored.
///
/// # Example
///
/// ```
/// use arrow2::array::BooleanArray;
/// use arrow2::compute::boolean::any;
///
/// let a = BooleanArray::from(&[Some(true), Some(false)]);
/// let b = BooleanArray::from(&[Some(false), Some(false)]);
/// let c = BooleanArray::from(&[None, Some(false)]);
///
/// assert_eq!(any(&a), true);
/// assert_eq!(any(&b), false);
/// assert_eq!(any(&c), false);
/// ```
pub fn any(array: &BooleanArray) -> bool {
if array.is_empty() {
false
} else if array.validity().is_some() {
} else if array.null_count() > 0 {
array.into_iter().any(|v| v == Some(true))
} else {
let vals = array.values();
vals.unset_bits() != vals.len()
}
}

/// Check if all of the values in the array are `true`
/// Returns whether all values in the array are `true`.
///
/// Null values are ignored.
///
/// # Example
///
/// ```
/// use arrow2::array::BooleanArray;
/// use arrow2::compute::boolean::all;
///
/// let a = BooleanArray::from(&[Some(true), Some(true)]);
/// let b = BooleanArray::from(&[Some(false), Some(true)]);
/// let c = BooleanArray::from(&[None, Some(true)]);
///
/// assert_eq!(all(&a), true);
/// assert_eq!(all(&b), false);
/// assert_eq!(all(&c), true);
/// ```
pub fn all(array: &BooleanArray) -> bool {
if array.is_empty() {
true
} else if array.null_count() > 0 {
false
!array.into_iter().any(|v| v == Some(false))
} else {
let vals = array.values();
vals.unset_bits() == 0
Expand Down
66 changes: 55 additions & 11 deletions src/compute/boolean_kleene.rs
Original file line number Diff line number Diff line change
Expand Up @@ -234,26 +234,70 @@ pub fn and_scalar(array: &BooleanArray, scalar: &BooleanScalar) -> BooleanArray
}
}

/// Returns whether any of the values in the array is `true`
pub fn any(array: &BooleanArray) -> bool {
/// Returns whether any of the values in the array are `true`.
///
/// The output is unknown (`None`) if the array contains any null values and
/// no `true` values.
///
/// # Example
///
/// ```
/// use arrow2::array::BooleanArray;
/// use arrow2::compute::boolean_kleene::any;
///
/// let a = BooleanArray::from(&[Some(true), Some(false)]);
/// let b = BooleanArray::from(&[Some(false), Some(false)]);
/// let c = BooleanArray::from(&[None, Some(false)]);
///
/// assert_eq!(any(&a), Some(true));
/// assert_eq!(any(&b), Some(false));
/// assert_eq!(any(&c), None);
/// ```
pub fn any(array: &BooleanArray) -> Option<bool> {
if array.is_empty() {
false
} else if array.validity().is_some() {
array.into_iter().any(|v| v == Some(true))
Some(false)
} else if array.null_count() > 0 {
if array.into_iter().any(|v| v == Some(true)) {
Some(true)
} else {
None
}
} else {
let vals = array.values();
vals.unset_bits() != vals.len()
Some(vals.unset_bits() != vals.len())
}
}

/// Returns whether all values in the array are `true`
pub fn all(array: &BooleanArray) -> bool {
/// Returns whether all values in the array are `true`.
///
/// The output is unknown (`None`) if the array contains any null values and
/// no `false` values.
///
/// # Example
///
/// ```
/// use arrow2::array::BooleanArray;
/// use arrow2::compute::boolean_kleene::all;
///
/// let a = BooleanArray::from(&[Some(true), Some(true)]);
/// let b = BooleanArray::from(&[Some(false), Some(true)]);
/// let c = BooleanArray::from(&[None, Some(true)]);
///
/// assert_eq!(all(&a), Some(true));
/// assert_eq!(all(&b), Some(false));
/// assert_eq!(all(&c), None);
/// ```
pub fn all(array: &BooleanArray) -> Option<bool> {
if array.is_empty() {
true
Some(true)
} else if array.null_count() > 0 {
false
if array.into_iter().any(|v| v == Some(false)) {
Some(false)
} else {
None
}
} else {
let vals = array.values();
vals.unset_bits() == 0
Some(vals.unset_bits() == 0)
}
}
9 changes: 6 additions & 3 deletions tests/it/compute/boolean.rs
Original file line number Diff line number Diff line change
Expand Up @@ -429,21 +429,24 @@ fn test_any_all() {
assert!(!any(&array));
assert!(!all(&array));
let array = BooleanArray::from(&[None, Some(true), Some(true)]);
assert!(!all(&array));
assert!(any(&array));
assert!(all(&array));
let array = BooleanArray::from_iter(std::iter::repeat(false).take(10).map(Some));
assert!(!any(&array));
assert!(!all(&array));
let array = BooleanArray::from_iter(std::iter::repeat(true).take(10).map(Some));
assert!(all(&array));
assert!(any(&array));
assert!(all(&array));
let array = BooleanArray::from_iter([true, false, true, true].map(Some));
assert!(!all(&array));
assert!(any(&array));
assert!(!all(&array));
let array = BooleanArray::from(&[Some(true)]);
assert!(any(&array));
assert!(all(&array));
let array = BooleanArray::from(&[Some(false)]);
assert!(!any(&array));
assert!(!all(&array));
let array = BooleanArray::from(&[]);
assert!(!any(&array));
assert!(all(&array));
}
4 changes: 2 additions & 2 deletions tests/it/compute/boolean_kleene.rs
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,6 @@ fn array_or_none() {
#[test]
fn array_empty() {
let array = BooleanArray::from(&[]);
assert!(!any(&array));
assert!(all(&array));
assert_eq!(any(&array), Some(false));
assert_eq!(all(&array), Some(true));
}

0 comments on commit 5720d9a

Please sign in to comment.