#[cfg(feature = "list_to_struct")]
use std::sync::RwLock;
use polars_core::prelude::*;
#[cfg(feature = "diff")]
use polars_core::series::ops::NullBehavior;
use polars_ops::prelude::*;
use crate::dsl::function_expr::FunctionExpr;
use crate::prelude::function_expr::ListFunction;
use crate::prelude::*;
pub struct ListNameSpace(pub Expr);
impl ListNameSpace {
pub fn lengths(self) -> Expr {
let function = |s: Series| {
let ca = s.list()?;
Ok(ca.lst_lengths().into_series())
};
self.0
.map(function, GetOutput::from_type(IDX_DTYPE))
.with_fmt("arr.len")
}
pub fn max(self) -> Expr {
self.0
.map(
|s| Ok(s.list()?.lst_max()),
GetOutput::map_field(|f| {
if let DataType::List(adt) = f.data_type() {
Field::new(f.name(), *adt.clone())
} else {
f.clone()
}
}),
)
.with_fmt("arr.max")
}
pub fn min(self) -> Expr {
self.0
.map(
|s| Ok(s.list()?.lst_min()),
GetOutput::map_field(|f| {
if let DataType::List(adt) = f.data_type() {
Field::new(f.name(), *adt.clone())
} else {
f.clone()
}
}),
)
.with_fmt("arr.min")
}
pub fn sum(self) -> Expr {
self.0
.map(
|s| Ok(s.list()?.lst_sum()),
GetOutput::map_field(|f| {
if let DataType::List(adt) = f.data_type() {
Field::new(f.name(), *adt.clone())
} else {
f.clone()
}
}),
)
.with_fmt("arr.sum")
}
pub fn mean(self) -> Expr {
self.0
.map(
|s| Ok(s.list()?.lst_mean().into_series()),
GetOutput::from_type(DataType::Float64),
)
.with_fmt("arr.mean")
}
pub fn sort(self, options: SortOptions) -> Expr {
self.0
.map(
move |s| Ok(s.list()?.lst_sort(options).into_series()),
GetOutput::same_type(),
)
.with_fmt("arr.sort")
}
pub fn reverse(self) -> Expr {
self.0
.map(
move |s| Ok(s.list()?.lst_reverse().into_series()),
GetOutput::same_type(),
)
.with_fmt("arr.reverse")
}
pub fn unique(self) -> Expr {
self.0
.map(
move |s| Ok(s.list()?.lst_unique()?.into_series()),
GetOutput::same_type(),
)
.with_fmt("arr.unique")
}
pub fn get(self, index: Expr) -> Expr {
self.0
.map_many_private(FunctionExpr::ListExpr(ListFunction::Get), &[index], false)
}
pub fn first(self) -> Expr {
self.get(lit(0i64))
}
pub fn last(self) -> Expr {
self.get(lit(-1i64))
}
pub fn join(self, separator: &str) -> Expr {
let separator = separator.to_string();
self.0
.map(
move |s| s.list()?.lst_join(&separator).map(|ca| ca.into_series()),
GetOutput::from_type(DataType::Utf8),
)
.with_fmt("arr.join")
}
pub fn arg_min(self) -> Expr {
self.0
.map(
|s| Ok(s.list()?.lst_arg_min().into_series()),
GetOutput::from_type(IDX_DTYPE),
)
.with_fmt("arr.arg_min")
}
pub fn arg_max(self) -> Expr {
self.0
.map(
|s| Ok(s.list()?.lst_arg_max().into_series()),
GetOutput::from_type(IDX_DTYPE),
)
.with_fmt("arr.arg_max")
}
#[cfg(feature = "diff")]
#[cfg_attr(docsrs, doc(cfg(feature = "diff")))]
pub fn diff(self, n: usize, null_behavior: NullBehavior) -> Expr {
self.0
.map(
move |s| Ok(s.list()?.lst_diff(n, null_behavior).into_series()),
GetOutput::same_type(),
)
.with_fmt("arr.diff")
}
pub fn shift(self, periods: i64) -> Expr {
self.0
.map(
move |s| Ok(s.list()?.lst_shift(periods).into_series()),
GetOutput::same_type(),
)
.with_fmt("arr.shift")
}
pub fn slice(self, offset: Expr, length: Expr) -> Expr {
self.0.map_many_private(
FunctionExpr::ListExpr(ListFunction::Slice),
&[offset, length],
false,
)
}
pub fn head(self, n: Expr) -> Expr {
self.slice(lit(0), n)
}
pub fn tail(self, n: Expr) -> Expr {
self.slice(lit(0) - n.clone().cast(DataType::Int64), n)
}
#[cfg(feature = "list_to_struct")]
#[cfg_attr(docsrs, doc(cfg(feature = "list_to_struct")))]
#[allow(clippy::wrong_self_convention)]
pub fn to_struct(
self,
n_fields: ListToStructWidthStrategy,
name_generator: Option<NameGenerator>,
upper_bound: usize,
) -> Expr {
let out_dtype = Arc::new(RwLock::new(None::<DataType>));
self.0
.map(
move |s| {
s.list()?
.to_struct(n_fields, name_generator.clone())
.map(|s| s.into_series())
},
GetOutput::map_dtype(move |dt: &DataType| {
let out = out_dtype.read().unwrap();
match out.as_ref() {
Some(dt) => dt.clone(),
None => {
drop(out);
let mut lock = out_dtype.write().unwrap();
let inner = dt.inner_dtype().unwrap();
let fields = (0..upper_bound)
.map(|i| {
let name = _default_struct_name_gen(i);
Field::from_owned(name, inner.clone())
})
.collect();
let dt = DataType::Struct(fields);
*lock = Some(dt.clone());
dt
}
}
}),
)
.with_fmt("arr.to_struct")
}
#[cfg(feature = "is_in")]
#[cfg_attr(docsrs, doc(cfg(feature = "is_in")))]
pub fn contains<E: Into<Expr>>(self, other: E) -> Expr {
let other = other.into();
Expr::Function {
input: vec![self.0, other],
function: FunctionExpr::ListExpr(ListFunction::Contains),
options: FunctionOptions {
collect_groups: ApplyOptions::ApplyFlat,
input_wildcard_expansion: true,
auto_explode: true,
fmt_str: "arr.contains",
..Default::default()
},
}
}
}