Path: blob/main/crates/polars-expr/src/dispatch/struct_.rs
7884 views
use std::sync::Arc;12use polars_core::error::{PolarsResult, polars_err};3use polars_core::prelude::{4Column, InitHashMaps, IntoColumn, PlIndexMap, StringChunked, StructChunked,5};6use polars_plan::dsl::{ColumnsUdf, SpecialEq};7use polars_plan::plans::IRStructFunction;8use polars_plan::prelude::PlanCallback;9use polars_utils::format_pl_smallstr;10use polars_utils::pl_str::PlSmallStr;1112pub fn function_expr_to_udf(func: IRStructFunction) -> SpecialEq<Arc<dyn ColumnsUdf>> {13use IRStructFunction::*;14match func {15FieldByName(name) => map!(get_by_name, &name),16RenameFields(names) => map!(rename_fields, names.clone()),17PrefixFields(prefix) => map!(prefix_fields, prefix.as_str()),18SuffixFields(suffix) => map!(suffix_fields, suffix.as_str()),19#[cfg(feature = "json")]20JsonEncode => map!(to_json),21WithFields => map_as_slice!(with_fields),22MapFieldNames(function) => map!(map_field_names, &function),23}24}2526pub(super) fn get_by_name(s: &Column, name: &str) -> PolarsResult<Column> {27let ca = s.struct_()?;28ca.field_by_name(name).map(Column::from)29}3031pub(super) fn rename_fields(s: &Column, names: Arc<[PlSmallStr]>) -> PolarsResult<Column> {32let ca = s.struct_()?;33let fields = ca34.fields_as_series()35.iter()36.zip(names.as_ref())37.map(|(s, name)| {38let mut s = s.clone();39s.rename(name.clone());40s41})42.collect::<Vec<_>>();43let mut out = StructChunked::from_series(ca.name().clone(), ca.len(), fields.iter())?;44out.zip_outer_validity(ca);45Ok(out.into_column())46}4748pub(super) fn prefix_fields(s: &Column, prefix: &str) -> PolarsResult<Column> {49let ca = s.struct_()?;50let fields = ca51.fields_as_series()52.iter()53.map(|s| {54let mut s = s.clone();55let name = s.name();56s.rename(format_pl_smallstr!("{prefix}{name}"));57s58})59.collect::<Vec<_>>();60let mut out = StructChunked::from_series(ca.name().clone(), ca.len(), fields.iter())?;61out.zip_outer_validity(ca);62Ok(out.into_column())63}6465pub(super) fn suffix_fields(s: &Column, suffix: &str) -> PolarsResult<Column> {66let ca = s.struct_()?;67let fields = ca68.fields_as_series()69.iter()70.map(|s| {71let mut s = s.clone();72let name = s.name();73s.rename(format_pl_smallstr!("{name}{suffix}"));74s75})76.collect::<Vec<_>>();77let mut out = StructChunked::from_series(ca.name().clone(), ca.len(), fields.iter())?;78out.zip_outer_validity(ca);79Ok(out.into_column())80}8182#[cfg(feature = "json")]83pub(super) fn to_json(s: &Column) -> PolarsResult<Column> {84use polars_core::prelude::CompatLevel;8586let ca = s.struct_()?;87let dtype = ca.dtype().to_arrow(CompatLevel::newest());8889let iter = ca.chunks().iter().map(|arr| {90let arr = polars_compute::cast::cast_unchecked(arr.as_ref(), &dtype).unwrap();91polars_json::json::write::serialize_to_utf8(arr.as_ref())92});9394Ok(StringChunked::from_chunk_iter(ca.name().clone(), iter).into_column())95}9697pub(super) fn with_fields(args: &[Column]) -> PolarsResult<Column> {98let s = &args[0];99100let ca = s.struct_()?;101let current = ca.fields_as_series();102103let mut fields = PlIndexMap::with_capacity(current.len() + s.len() - 1);104105for field in current.iter() {106fields.insert(field.name(), field);107}108109for field in &args[1..] {110fields.insert(field.name(), field.as_materialized_series());111}112113let new_fields = fields.into_values().cloned().collect::<Vec<_>>();114let mut out = StructChunked::from_series(ca.name().clone(), ca.len(), new_fields.iter())?;115out.zip_outer_validity(ca);116Ok(out.into_column())117}118119pub(super) fn map_field_names(120s: &Column,121function: &PlanCallback<PlSmallStr, PlSmallStr>,122) -> PolarsResult<Column> {123let ca = s.struct_()?;124let fields = ca125.fields_as_series()126.iter()127.map(|s| {128let mut s = s.clone();129let name = s.name();130let new_name = function.call(name.clone()).map_err(131|e| polars_err!(ComputeError: "'name.map_fields' produced an error: {e}."),132)?;133s.rename(new_name);134Ok(s)135})136.collect::<PolarsResult<Vec<_>>>()?;137let mut out = StructChunked::from_series(ca.name().clone(), ca.len(), fields.iter())?;138out.zip_outer_validity(ca);139Ok(out.into_column())140}141142143