polars_core/chunked_array/builder/
mod.rs1mod boolean;
2#[cfg(feature = "dtype-array")]
3pub mod fixed_size_list;
4pub mod list;
5mod null;
6mod primitive;
7mod string;
8
9use std::sync::Arc;
10
11use arrow::array::*;
12use arrow::bitmap::Bitmap;
13pub use boolean::*;
14#[cfg(feature = "dtype-array")]
15pub(crate) use fixed_size_list::*;
16pub use list::*;
17pub use null::*;
18pub use primitive::*;
19pub use string::*;
20
21use crate::chunked_array::to_primitive;
22use crate::prelude::*;
23use crate::utils::{NoNull, get_iter_capacity};
24
25pub trait ChunkedBuilder<N, T: PolarsDataType> {
27 fn append_value(&mut self, val: N);
28 fn append_null(&mut self);
29 fn append_option(&mut self, opt_val: Option<N>) {
30 match opt_val {
31 Some(v) => self.append_value(v),
32 None => self.append_null(),
33 }
34 }
35 fn finish(self) -> ChunkedArray<T>;
36
37 fn shrink_to_fit(&mut self);
38}
39
40impl<T> FromIterator<(Vec<T::Native>, Option<Bitmap>)> for ChunkedArray<T>
42where
43 T: PolarsNumericType,
44{
45 fn from_iter<I: IntoIterator<Item = (Vec<T::Native>, Option<Bitmap>)>>(iter: I) -> Self {
46 let chunks = iter
47 .into_iter()
48 .map(|(values, opt_buffer)| to_primitive::<T>(values, opt_buffer));
49 ChunkedArray::from_chunk_iter(PlSmallStr::EMPTY, chunks)
50 }
51}
52
53pub trait NewChunkedArray<T, N> {
54 fn from_slice(name: PlSmallStr, v: &[N]) -> Self;
55 fn from_slice_options(name: PlSmallStr, opt_v: &[Option<N>]) -> Self;
56
57 fn from_iter_options(name: PlSmallStr, it: impl Iterator<Item = Option<N>>) -> Self;
59
60 fn from_iter_values(name: PlSmallStr, it: impl Iterator<Item = N>) -> Self;
62}
63
64impl<T> NewChunkedArray<T, T::Native> for ChunkedArray<T>
65where
66 T: PolarsNumericType,
67{
68 fn from_slice(name: PlSmallStr, v: &[T::Native]) -> Self {
69 let arr = PrimitiveArray::from_slice(v).to(T::get_dtype().to_arrow(CompatLevel::newest()));
70 ChunkedArray::with_chunk(name, arr)
71 }
72
73 fn from_slice_options(name: PlSmallStr, opt_v: &[Option<T::Native>]) -> Self {
74 Self::from_iter_options(name, opt_v.iter().copied())
75 }
76
77 fn from_iter_options(
78 name: PlSmallStr,
79 it: impl Iterator<Item = Option<T::Native>>,
80 ) -> ChunkedArray<T> {
81 let mut builder = PrimitiveChunkedBuilder::new(name, get_iter_capacity(&it));
82 it.for_each(|opt| builder.append_option(opt));
83 builder.finish()
84 }
85
86 fn from_iter_values(name: PlSmallStr, it: impl Iterator<Item = T::Native>) -> ChunkedArray<T> {
88 let ca: NoNull<ChunkedArray<_>> = it.collect();
89 let mut ca = ca.into_inner();
90 ca.rename(name);
91 ca
92 }
93}
94
95impl NewChunkedArray<BooleanType, bool> for BooleanChunked {
96 fn from_slice(name: PlSmallStr, v: &[bool]) -> Self {
97 Self::from_iter_values(name, v.iter().copied())
98 }
99
100 fn from_slice_options(name: PlSmallStr, opt_v: &[Option<bool>]) -> Self {
101 Self::from_iter_options(name, opt_v.iter().copied())
102 }
103
104 fn from_iter_options(
105 name: PlSmallStr,
106 it: impl Iterator<Item = Option<bool>>,
107 ) -> ChunkedArray<BooleanType> {
108 let mut builder = BooleanChunkedBuilder::new(name, get_iter_capacity(&it));
109 it.for_each(|opt| builder.append_option(opt));
110 builder.finish()
111 }
112
113 fn from_iter_values(
115 name: PlSmallStr,
116 it: impl Iterator<Item = bool>,
117 ) -> ChunkedArray<BooleanType> {
118 let mut ca: ChunkedArray<_> = it.collect();
119 ca.rename(name);
120 ca
121 }
122}
123
124impl<S> NewChunkedArray<StringType, S> for StringChunked
125where
126 S: AsRef<str>,
127{
128 fn from_slice(name: PlSmallStr, v: &[S]) -> Self {
129 let arr = Utf8ViewArray::from_slice_values(v);
130 ChunkedArray::with_chunk(name, arr)
131 }
132
133 fn from_slice_options(name: PlSmallStr, opt_v: &[Option<S>]) -> Self {
134 let arr = Utf8ViewArray::from_slice(opt_v);
135 ChunkedArray::with_chunk(name, arr)
136 }
137
138 fn from_iter_options(name: PlSmallStr, it: impl Iterator<Item = Option<S>>) -> Self {
139 let arr = MutableBinaryViewArray::from_iterator(it).freeze();
140 ChunkedArray::with_chunk(name, arr)
141 }
142
143 fn from_iter_values(name: PlSmallStr, it: impl Iterator<Item = S>) -> Self {
145 let arr = MutableBinaryViewArray::from_values_iter(it).freeze();
146 ChunkedArray::with_chunk(name, arr)
147 }
148}
149
150impl<B> NewChunkedArray<BinaryType, B> for BinaryChunked
151where
152 B: AsRef<[u8]>,
153{
154 fn from_slice(name: PlSmallStr, v: &[B]) -> Self {
155 let arr = BinaryViewArray::from_slice_values(v);
156 ChunkedArray::with_chunk(name, arr)
157 }
158
159 fn from_slice_options(name: PlSmallStr, opt_v: &[Option<B>]) -> Self {
160 let arr = BinaryViewArray::from_slice(opt_v);
161 ChunkedArray::with_chunk(name, arr)
162 }
163
164 fn from_iter_options(name: PlSmallStr, it: impl Iterator<Item = Option<B>>) -> Self {
165 let arr = MutableBinaryViewArray::from_iterator(it).freeze();
166 ChunkedArray::with_chunk(name, arr)
167 }
168
169 fn from_iter_values(name: PlSmallStr, it: impl Iterator<Item = B>) -> Self {
171 let arr = MutableBinaryViewArray::from_values_iter(it).freeze();
172 ChunkedArray::with_chunk(name, arr)
173 }
174}
175
176#[cfg(test)]
177mod test {
178 use super::*;
179
180 #[test]
181 fn test_primitive_builder() {
182 let mut builder =
183 PrimitiveChunkedBuilder::<UInt32Type>::new(PlSmallStr::from_static("foo"), 6);
184 let values = &[Some(1), None, Some(2), Some(3), None, Some(4)];
185 for val in values {
186 builder.append_option(*val);
187 }
188 let ca = builder.finish();
189 assert_eq!(Vec::from(&ca), values);
190 }
191
192 #[test]
193 fn test_list_builder() {
194 let mut builder = ListPrimitiveChunkedBuilder::<Int32Type>::new(
195 PlSmallStr::from_static("a"),
196 10,
197 5,
198 DataType::Int32,
199 );
200
201 let mut s1 =
203 Int32Chunked::from_slice(PlSmallStr::from_static("a"), &[1, 2, 3]).into_series();
204 let s2 = Int32Chunked::from_slice(PlSmallStr::from_static("b"), &[4, 5, 6]).into_series();
205 s1.append(&s2).unwrap();
206
207 builder.append_series(&s1).unwrap();
208 builder.append_series(&s2).unwrap();
209 let ls = builder.finish();
210 if let AnyValue::List(s) = ls.get_any_value(0).unwrap() {
211 assert_eq!(s.len(), 6)
213 } else {
214 panic!()
215 }
216 if let AnyValue::List(s) = ls.get_any_value(1).unwrap() {
217 assert_eq!(s.len(), 3)
218 } else {
219 panic!()
220 }
221
222 let out = [&s1, &s2].iter().copied().collect::<ListChunked>();
224 assert_eq!(out.get_as_series(0).unwrap().len(), 6);
225 assert_eq!(out.get_as_series(1).unwrap().len(), 3);
226
227 let mut builder = ListPrimitiveChunkedBuilder::<Int32Type>::new(
228 PlSmallStr::from_static("a"),
229 10,
230 5,
231 DataType::Int32,
232 );
233 builder.append_series(&s1).unwrap();
234 builder.append_null();
235
236 let out = builder.finish();
237 let out = out.explode().unwrap();
238 assert_eq!(out.len(), 7);
239 assert_eq!(out.get(6).unwrap(), AnyValue::Null);
240 }
241}