axion_data/series/
string.rs

1use super::core::Series;
2use crate::error::AxionResult;
3use crate::dtype::DataType;
4
5/// 字符串 Series 的专用操作访问器
6/// 
7/// 提供了专门针对 `Series<String>` 的字符串处理方法,
8/// 包括模式匹配、大小写转换、空白字符处理等功能。
9/// 
10/// # 使用方式
11/// 
12/// 通过 `Series<String>` 的 `.str()` 方法获取该访问器实例。
13/// 
14/// # 示例
15/// 
16/// ```rust
17/// let s = Series::new("names".to_string(), vec!["Alice", "Bob", "Charlie"]);
18/// let contains_result = s.str().contains("a")?;
19/// let uppercase_result = s.str().to_uppercase()?;
20/// ```
21pub struct StringAccessor<'a> {
22    series: &'a Series<String>,
23}
24
25impl<'a> StringAccessor<'a> {
26    /// 创建新的 StringAccessor 实例
27    /// 
28    /// # 参数
29    /// 
30    /// * `series` - 字符串类型的 Series 引用
31    /// 
32    /// # Panics
33    /// 
34    /// 如果 Series 的数据类型不是 String 则会 panic
35    pub(super) fn new(series: &'a Series<String>) -> Self {
36        assert_eq!(series.dtype(), DataType::String, "StringAccessor can only be used on Series<String>");
37        Self { series }
38    }
39
40    /// 检查元素是否包含指定模式
41    /// 
42    /// # 参数
43    /// 
44    /// * `pattern` - 要搜索的字符串模式
45    /// 
46    /// # 返回值
47    /// 
48    /// 返回新的布尔类型 Series,null 值保持为 null
49    pub fn contains(&self, pattern: &str) -> AxionResult<Series<bool>> {
50        let new_name = format!("{}_contains_{}", self.series.name(), pattern);
51        if self.series.is_empty() {
52            return Ok(Series::new_empty(new_name, DataType::Bool));
53        }
54        let new_data: Vec<Option<bool>> = self.series.data.iter()
55            .map(|opt_s| opt_s.as_ref().map(|s| s.contains(pattern)))
56            .collect();
57        Ok(Series::new_from_options(new_name, new_data))
58    }
59
60    /// 检查元素是否以指定模式开头
61    /// 
62    /// # 参数
63    /// 
64    /// * `pattern` - 要检查的前缀模式
65    /// 
66    /// # 返回值
67    /// 
68    /// 返回新的布尔类型 Series,null 值保持为 null
69    pub fn startswith(&self, pattern: &str) -> AxionResult<Series<bool>> {
70        let new_name = format!("{}_startswith_{}", self.series.name(), pattern);
71        if self.series.is_empty() {
72            return Ok(Series::new_empty(new_name, DataType::Bool));
73        }
74        let new_data: Vec<Option<bool>> = self.series.data.iter()
75            .map(|opt_s| opt_s.as_ref().map(|s| s.starts_with(pattern)))
76            .collect();
77        Ok(Series::new_from_options(new_name, new_data))
78    }
79
80    /// 检查元素是否以指定模式结尾
81    /// 
82    /// # 参数
83    /// 
84    /// * `pattern` - 要检查的后缀模式
85    /// 
86    /// # 返回值
87    /// 
88    /// 返回新的布尔类型 Series,null 值保持为 null
89    pub fn endswith(&self, pattern: &str) -> AxionResult<Series<bool>> {
90        let new_name = format!("{}_endswith_{}", self.series.name(), pattern);
91        if self.series.is_empty() {
92            return Ok(Series::new_empty(new_name, DataType::Bool));
93        }
94        let new_data: Vec<Option<bool>> = self.series.data.iter()
95            .map(|opt_s| opt_s.as_ref().map(|s| s.ends_with(pattern)))
96            .collect();
97        Ok(Series::new_from_options(new_name, new_data))
98    }
99
100    /// 获取每个字符串元素的长度(字节数)
101    /// 
102    /// # 返回值
103    /// 
104    /// 返回新的 u32 类型 Series,null 值保持为 null
105    pub fn str_len(&self) -> AxionResult<Series<u32>> {
106        let new_name = format!("{}_len", self.series.name());
107        if self.series.is_empty() {
108            return Ok(Series::new_empty(new_name, DataType::UInt32));
109        }
110        let new_data: Vec<Option<u32>> = self.series.data.iter()
111            .map(|opt_s| opt_s.as_ref().map(|s| s.len() as u32))
112            .collect();
113        Ok(Series::new_from_options(new_name, new_data))
114    }
115
116    /// 替换所有匹配的模式
117    /// 
118    /// # 参数
119    /// 
120    /// * `from` - 要替换的模式
121    /// * `to` - 替换后的字符串
122    /// 
123    /// # 返回值
124    /// 
125    /// 返回新的字符串 Series,null 值保持为 null
126    pub fn replace(&self, from: &str, to: &str) -> AxionResult<Series<String>> {
127        let new_name = format!("{}_replace", self.series.name());
128        if self.series.is_empty() {
129            return Ok(Series::new_empty(new_name, DataType::String));
130        }
131        let new_data: Vec<Option<String>> = self.series.data.iter()
132            .map(|opt_s| opt_s.as_ref().map(|s| s.replace(from, to)))
133            .collect();
134        Ok(Series::new_from_options(new_name, new_data))
135    }
136
137    /// 转换为小写
138    /// 
139    /// # 返回值
140    /// 
141    /// 返回新的字符串 Series,所有字符转换为小写,null 值保持为 null
142    pub fn to_lowercase(&self) -> AxionResult<Series<String>> {
143        let new_name = format!("{}_lower", self.series.name());
144        if self.series.is_empty() {
145            return Ok(Series::new_empty(new_name, DataType::String));
146        }
147        let new_data: Vec<Option<String>> = self.series.data.iter()
148            .map(|opt_s| opt_s.as_ref().map(|s| s.to_lowercase()))
149            .collect();
150        Ok(Series::new_from_options(new_name, new_data))
151    }
152
153    /// 转换为大写
154    /// 
155    /// # 返回值
156    /// 
157    /// 返回新的字符串 Series,所有字符转换为大写,null 值保持为 null
158    pub fn to_uppercase(&self) -> AxionResult<Series<String>> {
159        let new_name = format!("{}_upper", self.series.name());
160        if self.series.is_empty() {
161            return Ok(Series::new_empty(new_name, DataType::String));
162        }
163        let new_data: Vec<Option<String>> = self.series.data.iter()
164            .map(|opt_s| opt_s.as_ref().map(|s| s.to_uppercase()))
165            .collect();
166        Ok(Series::new_from_options(new_name, new_data))
167    }
168
169    /// 去除首尾空白字符
170    /// 
171    /// # 返回值
172    /// 
173    /// 返回新的字符串 Series,去除每个字符串的首尾空白字符,null 值保持为 null
174    pub fn strip(&self) -> AxionResult<Series<String>> {
175        let new_name = format!("{}_strip", self.series.name());
176        if self.series.is_empty() {
177            return Ok(Series::new_empty(new_name, DataType::String));
178        }
179        let new_data: Vec<Option<String>> = self.series.data.iter()
180            .map(|opt_s| opt_s.as_ref().map(|s| s.trim().to_string()))
181            .collect();
182        Ok(Series::new_from_options(new_name, new_data))
183    }
184
185    /// 去除开头的空白字符
186    /// 
187    /// # 返回值
188    /// 
189    /// 返回新的字符串 Series,去除每个字符串开头的空白字符,null 值保持为 null
190    pub fn lstrip(&self) -> AxionResult<Series<String>> {
191        let new_name = format!("{}_lstrip", self.series.name());
192        if self.series.is_empty() {
193            return Ok(Series::new_empty(new_name, DataType::String));
194        }
195        let new_data: Vec<Option<String>> = self.series.data.iter()
196            .map(|opt_s| opt_s.as_ref().map(|s| s.trim_start().to_string()))
197            .collect();
198        Ok(Series::new_from_options(new_name, new_data))
199    }
200
201    /// 去除末尾的空白字符
202    /// 
203    /// # 返回值
204    /// 
205    /// 返回新的字符串 Series,去除每个字符串末尾的空白字符,null 值保持为 null
206    pub fn rstrip(&self) -> AxionResult<Series<String>> {
207        let new_name = format!("{}_rstrip", self.series.name());
208        if self.series.is_empty() {
209            return Ok(Series::new_empty(new_name, DataType::String));
210        }
211        let new_data: Vec<Option<String>> = self.series.data.iter()
212            .map(|opt_s| opt_s.as_ref().map(|s| s.trim_end().to_string()))
213            .collect();
214        Ok(Series::new_from_options(new_name, new_data))
215    }
216}