Path: blob/main/crates/polars-expr/src/dispatch/struct_.rs
8412 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),21MapFieldNames(function) => map!(map_field_names, &function),22}23}2425pub(super) fn get_by_name(s: &Column, name: &str) -> PolarsResult<Column> {26let ca = s.struct_()?;27ca.field_by_name(name).map(Column::from)28}2930pub(super) fn rename_fields(s: &Column, names: Arc<[PlSmallStr]>) -> PolarsResult<Column> {31let ca = s.struct_()?;32let fields = ca33.fields_as_series()34.iter()35.zip(names.as_ref())36.map(|(s, name)| {37let mut s = s.clone();38s.rename(name.clone());39s40})41.collect::<Vec<_>>();42let mut out = StructChunked::from_series(ca.name().clone(), ca.len(), fields.iter())?;43out.zip_outer_validity(ca);44Ok(out.into_column())45}4647pub(super) fn prefix_fields(s: &Column, prefix: &str) -> PolarsResult<Column> {48let ca = s.struct_()?;49let fields = ca50.fields_as_series()51.iter()52.map(|s| {53let mut s = s.clone();54let name = s.name();55s.rename(format_pl_smallstr!("{prefix}{name}"));56s57})58.collect::<Vec<_>>();59let mut out = StructChunked::from_series(ca.name().clone(), ca.len(), fields.iter())?;60out.zip_outer_validity(ca);61Ok(out.into_column())62}6364pub(super) fn suffix_fields(s: &Column, suffix: &str) -> PolarsResult<Column> {65let ca = s.struct_()?;66let fields = ca67.fields_as_series()68.iter()69.map(|s| {70let mut s = s.clone();71let name = s.name();72s.rename(format_pl_smallstr!("{name}{suffix}"));73s74})75.collect::<Vec<_>>();76let mut out = StructChunked::from_series(ca.name().clone(), ca.len(), fields.iter())?;77out.zip_outer_validity(ca);78Ok(out.into_column())79}8081#[cfg(feature = "json")]82pub(super) fn to_json(col: &Column) -> PolarsResult<Column> {83use polars_core::prelude::CompatLevel;8485let s = col.as_materialized_series();86let iter = (0..s.n_chunks()).map(|i| {87polars_json::json::write::serialize_to_utf8(&*s.to_arrow(i, CompatLevel::newest()))88});8990Ok(StringChunked::from_chunk_iter(s.name().clone(), iter).into_column())91}9293pub(crate) fn with_fields(args: &[Column]) -> PolarsResult<Column> {94let s = &args[0];9596let ca = s.struct_()?;97let current = ca.fields_as_series();9899let mut fields = PlIndexMap::with_capacity(current.len() + s.len() - 1);100101for field in current.iter() {102fields.insert(field.name(), field);103}104105for field in &args[1..] {106fields.insert(field.name(), field.as_materialized_series());107}108109let new_fields = fields.into_values().cloned().collect::<Vec<_>>();110let mut out = StructChunked::from_series(ca.name().clone(), ca.len(), new_fields.iter())?;111out.zip_outer_validity(ca);112Ok(out.into_column())113}114115pub(super) fn map_field_names(116s: &Column,117function: &PlanCallback<PlSmallStr, PlSmallStr>,118) -> PolarsResult<Column> {119let ca = s.struct_()?;120let fields = ca121.fields_as_series()122.iter()123.map(|s| {124let mut s = s.clone();125let name = s.name();126let new_name = function.call(name.clone()).map_err(127|e| polars_err!(ComputeError: "'name.map_fields' produced an error: {e}."),128)?;129s.rename(new_name);130Ok(s)131})132.collect::<PolarsResult<Vec<_>>>()?;133let mut out = StructChunked::from_series(ca.name().clone(), ca.len(), fields.iter())?;134out.zip_outer_validity(ca);135Ok(out.into_column())136}137138139