Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
pola-rs
GitHub Repository: pola-rs/polars
Path: blob/main/crates/polars-expr/src/dispatch/struct_.rs
7884 views
1
use std::sync::Arc;
2
3
use polars_core::error::{PolarsResult, polars_err};
4
use polars_core::prelude::{
5
Column, InitHashMaps, IntoColumn, PlIndexMap, StringChunked, StructChunked,
6
};
7
use polars_plan::dsl::{ColumnsUdf, SpecialEq};
8
use polars_plan::plans::IRStructFunction;
9
use polars_plan::prelude::PlanCallback;
10
use polars_utils::format_pl_smallstr;
11
use polars_utils::pl_str::PlSmallStr;
12
13
pub fn function_expr_to_udf(func: IRStructFunction) -> SpecialEq<Arc<dyn ColumnsUdf>> {
14
use IRStructFunction::*;
15
match func {
16
FieldByName(name) => map!(get_by_name, &name),
17
RenameFields(names) => map!(rename_fields, names.clone()),
18
PrefixFields(prefix) => map!(prefix_fields, prefix.as_str()),
19
SuffixFields(suffix) => map!(suffix_fields, suffix.as_str()),
20
#[cfg(feature = "json")]
21
JsonEncode => map!(to_json),
22
WithFields => map_as_slice!(with_fields),
23
MapFieldNames(function) => map!(map_field_names, &function),
24
}
25
}
26
27
pub(super) fn get_by_name(s: &Column, name: &str) -> PolarsResult<Column> {
28
let ca = s.struct_()?;
29
ca.field_by_name(name).map(Column::from)
30
}
31
32
pub(super) fn rename_fields(s: &Column, names: Arc<[PlSmallStr]>) -> PolarsResult<Column> {
33
let ca = s.struct_()?;
34
let fields = ca
35
.fields_as_series()
36
.iter()
37
.zip(names.as_ref())
38
.map(|(s, name)| {
39
let mut s = s.clone();
40
s.rename(name.clone());
41
s
42
})
43
.collect::<Vec<_>>();
44
let mut out = StructChunked::from_series(ca.name().clone(), ca.len(), fields.iter())?;
45
out.zip_outer_validity(ca);
46
Ok(out.into_column())
47
}
48
49
pub(super) fn prefix_fields(s: &Column, prefix: &str) -> PolarsResult<Column> {
50
let ca = s.struct_()?;
51
let fields = ca
52
.fields_as_series()
53
.iter()
54
.map(|s| {
55
let mut s = s.clone();
56
let name = s.name();
57
s.rename(format_pl_smallstr!("{prefix}{name}"));
58
s
59
})
60
.collect::<Vec<_>>();
61
let mut out = StructChunked::from_series(ca.name().clone(), ca.len(), fields.iter())?;
62
out.zip_outer_validity(ca);
63
Ok(out.into_column())
64
}
65
66
pub(super) fn suffix_fields(s: &Column, suffix: &str) -> PolarsResult<Column> {
67
let ca = s.struct_()?;
68
let fields = ca
69
.fields_as_series()
70
.iter()
71
.map(|s| {
72
let mut s = s.clone();
73
let name = s.name();
74
s.rename(format_pl_smallstr!("{name}{suffix}"));
75
s
76
})
77
.collect::<Vec<_>>();
78
let mut out = StructChunked::from_series(ca.name().clone(), ca.len(), fields.iter())?;
79
out.zip_outer_validity(ca);
80
Ok(out.into_column())
81
}
82
83
#[cfg(feature = "json")]
84
pub(super) fn to_json(s: &Column) -> PolarsResult<Column> {
85
use polars_core::prelude::CompatLevel;
86
87
let ca = s.struct_()?;
88
let dtype = ca.dtype().to_arrow(CompatLevel::newest());
89
90
let iter = ca.chunks().iter().map(|arr| {
91
let arr = polars_compute::cast::cast_unchecked(arr.as_ref(), &dtype).unwrap();
92
polars_json::json::write::serialize_to_utf8(arr.as_ref())
93
});
94
95
Ok(StringChunked::from_chunk_iter(ca.name().clone(), iter).into_column())
96
}
97
98
pub(super) fn with_fields(args: &[Column]) -> PolarsResult<Column> {
99
let s = &args[0];
100
101
let ca = s.struct_()?;
102
let current = ca.fields_as_series();
103
104
let mut fields = PlIndexMap::with_capacity(current.len() + s.len() - 1);
105
106
for field in current.iter() {
107
fields.insert(field.name(), field);
108
}
109
110
for field in &args[1..] {
111
fields.insert(field.name(), field.as_materialized_series());
112
}
113
114
let new_fields = fields.into_values().cloned().collect::<Vec<_>>();
115
let mut out = StructChunked::from_series(ca.name().clone(), ca.len(), new_fields.iter())?;
116
out.zip_outer_validity(ca);
117
Ok(out.into_column())
118
}
119
120
pub(super) fn map_field_names(
121
s: &Column,
122
function: &PlanCallback<PlSmallStr, PlSmallStr>,
123
) -> PolarsResult<Column> {
124
let ca = s.struct_()?;
125
let fields = ca
126
.fields_as_series()
127
.iter()
128
.map(|s| {
129
let mut s = s.clone();
130
let name = s.name();
131
let new_name = function.call(name.clone()).map_err(
132
|e| polars_err!(ComputeError: "'name.map_fields' produced an error: {e}."),
133
)?;
134
s.rename(new_name);
135
Ok(s)
136
})
137
.collect::<PolarsResult<Vec<_>>>()?;
138
let mut out = StructChunked::from_series(ca.name().clone(), ca.len(), fields.iter())?;
139
out.zip_outer_validity(ca);
140
Ok(out.into_column())
141
}
142
143