slice_reduce/
lib.rs

1//! # 切片工具库/Slice Utilities
2//! 
3//! 提供高效的切片操作函数/Provides efficient slice operations
4//! 
5//! ## 功能/Features
6//! - 分块/Chunking
7//! - 搜索/Searching
8//! - 统计/Counting
9//! - 排序相关/Sorting utilities
10
11use std::{cmp::{max, min, Ordering}, collections::HashMap};
12use rand::Rng;
13
14/// 将数组分块/Chunk an array into smaller arrays
15/// 
16/// # 参数/Arguments
17/// * `arr` - 要分块的数组/The array to chunk
18/// * `chunk_size` - 每个块的大小/The size of each chunk
19/// 
20/// # 返回值/Returns
21/// 包含分块结果的 `Vec<Vec<T>>`/A vector of vectors containing the chunks
22/// 
23/// # 示例/Examples
24/// ```
25/// use slice_reducer::chunk;
26/// let arr = vec![1, 2, 3, 4, 5];
27/// let chunks = chunk(&arr, 2);
28/// assert_eq!(chunks, vec![vec![1, 2], vec![3, 4], vec![5]]);
29/// ```
30/// 
31/// # 注意/Notes
32/// - 如果 `chunk_size` 为 0,返回空向量/If `chunk_size` is 0, returns empty vector
33/// - 最后一个块可能小于 `chunk_size`/Last chunk may be smaller than `chunk_size`
34pub fn chunk<T>(arr: &[T], chunk_size: usize) -> Vec<Vec<T>>
35where
36    T: Clone,
37{
38    let mut chunks: Vec<Vec<T>> = vec![];
39    if chunk_size == 0 {
40        chunks
41    } else {
42        for i in (0..arr.len()).step_by(chunk_size) {
43            let end = min(i + chunk_size, arr.len());
44            chunks.push(arr[i..end].to_vec());
45        }
46        chunks
47    }
48}
49
50/// 按指定键函数统计元素出现次数/Count elements by key function
51/// 
52/// # 参数/Arguments
53/// * `items` - 要统计的数组/The array to count
54/// * `key_of` - 生成统计键的函数/Function to generate key
55/// 
56/// # 返回值/Returns
57/// `HashMap<K, usize>` 键为统计键,值为出现次数/Key is the grouping key, value is count
58/// 
59/// # 示例/Examples
60/// ```
61/// use slice_reducer::count_by;
62/// let words = ["hello", "world"];
63/// let counts = count_by(&words, |s| s.len());
64/// assert_eq!(counts[&5], 2);
65/// ```
66pub fn count_by<T, K, F>(items: &[T], key_of: F) -> HashMap<K, usize>
67where
68    K: std::hash::Hash + Eq,
69    F: Fn(&T) -> K,
70{
71    let mut result = HashMap::<K, usize>::new();
72    for item in items {
73        let key = key_of(item);
74        let count = result.entry(key).or_insert(0);
75        *count += 1;
76    }
77    result
78}
79
80/// 统计元素出现次数/Count element occurrences
81/// 
82/// # 参数/Arguments
83/// * `items` - 要统计的数组/The array to count
84/// 
85/// # 返回值/Returns
86/// `HashMap<T, usize>` 键为元素,值为出现次数/Key is element, value is count
87/// 
88/// # 示例/Examples
89/// ```
90/// use slice_reducer::count;
91/// let nums = [1, 2, 2, 3];
92/// let counts = count(&nums);
93/// assert_eq!(counts[&2], 2);
94/// ```
95pub fn count<T>(items: &[T]) -> HashMap<T, usize>
96where
97    T: std::hash::Hash + Eq + Clone,
98{
99    count_by(items, Clone::clone)
100}
101
102/// 反转数组/Reverse an array
103/// 
104/// # 参数/Arguments
105/// * `arr` - 要反转的数组/The array to reverse
106/// 
107/// # 返回值/Returns
108/// 反转后的新数组/New array with elements reversed
109/// 
110/// # 示例/Examples
111/// ```
112/// use slice_reducer::reverse;
113/// let arr = [1, 2, 3];
114/// assert_eq!(reverse(&arr), [3, 2, 1]);
115/// ```
116pub fn reverse<T>(arr: &[T]) -> Vec<T>
117where
118    T: Clone,
119{
120    let mut result = arr.to_vec();
121    result.reverse();
122    result
123}
124
125/// 线性搜索/Linear search
126/// 
127/// # 参数/Arguments
128/// * `arr` - 要搜索的数组/The array to search
129/// * `target` - 要查找的目标/The target to find
130/// 
131/// # 返回值/Returns
132/// 目标索引(如果找到)/Index of target if found
133/// 
134/// # 示例/Examples
135/// ```
136/// use slice_reducer::linear_search;
137/// let arr = [10, 20, 30];
138/// assert_eq!(linear_search(&arr, &20), Some(1));
139/// assert_eq!(linear_search(&arr, &40), None);
140/// ```
141pub fn linear_search<T>(arr: &[T], target: &T) -> Option<usize>
142where
143    T: PartialEq,
144{
145    for (i, item) in arr.iter().enumerate() {
146        if item == target {
147            return Some(i);
148        }
149    }
150    None
151}
152
153/// 二分查找/Binary search (要求数组已排序/Array must be sorted)
154/// 
155/// # 参数/Arguments
156/// * `arr` - 已排序的数组/Sorted array to search
157/// * `target` - 要查找的目标/Target to find
158/// 
159/// # 返回值/Returns
160/// 目标索引(如果找到)/Index of target if found
161/// 
162/// # 示例/Examples
163/// ```
164/// use slice_reducer::binary_search;
165/// let arr = [10, 20, 30, 40];
166/// assert_eq!(binary_search(&arr, &20), Some(1));
167/// assert_eq!(binary_search(&arr, &25), None);
168/// ```
169pub fn binary_search<T>(arr: &[T], target: &T) -> Option<usize>
170where
171    T: Ord,
172{
173    let mut left = 0;
174    let mut right = arr.len() - 1;
175    while left <= right {
176        let mid = left + (right - left) / 2;
177        match arr[mid].cmp(target) {
178            std::cmp::Ordering::Less => left = mid + 1,
179            std::cmp::Ordering::Greater => right = mid - 1,
180            std::cmp::Ordering::Equal => return Some(mid),
181        }
182    }
183    None
184}
185
186/// 滑动窗口最大值/Sliding window maximum
187/// 
188/// # 参数/Arguments
189/// * `slice` - 输入数组/Input array
190/// * `window_size` - 窗口大小/Window size
191/// 
192/// # 返回值/Returns
193/// 每个窗口的最大值组成的数组/Array of each window's maximum
194/// 
195/// # 示例/Examples
196/// ```
197/// use slice_reducer::sliding_window_max;
198/// let arr = [1, 3, -1, -3, 5, 3];
199/// assert_eq!(sliding_window_max(&arr, 3), vec![3, 3, 5, 5]);
200/// ```
201/// 
202/// # 注意/Notes
203/// - 窗口大小必须 ≤ 数组长度/Window size must ≤ array length
204pub fn sliding_window_max(slice: &[i32], window_size: usize) -> Vec<i32> {
205    let mut result = vec![];
206    for i in 0..=slice.len() - window_size {
207        let window = &slice[i..i + window_size];
208        let max = window.iter().max().unwrap();
209        result.push(*max);
210    }
211    result
212}
213
214/// 合并两个已排序数组合并保持顺序/Merge two sorted arrays
215/// 
216/// # 参数/Arguments
217/// * `a` - 第一个已排序数组/First sorted array
218/// * `b` - 第二个已排序数组/Second sorted array
219/// 
220/// # 返回值/Returns
221/// 合并后的新数组/New merged array
222/// 
223/// # 示例/Examples
224/// ```
225/// use slice_reducer::merge_sorted;
226/// let a = [1, 3, 5];
227/// let b = [2, 4, 6];
228/// assert_eq!(merge_sorted(&a, &b), vec![1, 2, 3, 4, 5, 6]);
229/// ```
230pub fn merge_sorted<T: Ord + Clone>(a: &[T], b: &[T]) -> Vec<T> {
231    let mut merged = vec![];
232    let mut i = 0;
233    let mut j = 0;
234    while i < a.len() && j < b.len() {
235        if a[i] <= b[j] {
236            merged.push(a[i].clone());
237            i += 1;
238        } else {
239            merged.push(b[j].clone());
240            j += 1;
241        }
242    }
243    while i < a.len() {
244        merged.push(a[i].clone());
245        i += 1;
246    }
247    while j < b.len() {
248        merged.push(b[j].clone());
249        j += 1;
250    }
251    merged
252}
253
254/// 查找字符串数组的最长公共前缀/Longest common prefix of strings
255/// 
256/// # 参数/Arguments
257/// * `strs` - 字符串数组/String array
258/// 
259/// # 返回值/Returns
260/// 最长公共前缀字符串/Longest common prefix string
261/// 
262/// # 示例/Examples
263/// ```
264/// use slice_reducer::longest_common_prefix;
265/// let strs = ["flower", "flow", "flight"];
266/// assert_eq!(longest_common_prefix(&strs), "fl");
267/// ```
268pub fn longest_common_prefix(strs: &[&str]) -> String {
269    if strs.is_empty() {
270        return "".to_string();
271    }
272    let mut prefix = strs[0].to_string();
273    for s in strs.iter().skip(1) {
274        while !s.starts_with(&prefix) {
275            prefix.pop();
276            if prefix.is_empty() {
277                return "".to_string();
278            }
279        }
280    }
281    prefix
282}
283
284/// 最大子数组和(Kadane算法)/Maximum subarray sum (Kadane's algorithm)
285/// 
286/// # 参数/Arguments
287/// * `slice` - 输入数组/Input array
288/// 
289/// # 返回值/Returns
290/// 最大子数组和/Maximum subarray sum
291/// 
292/// # 示例/Examples
293/// ```
294/// use slice_reducer::max_subarray_sum;
295/// let arr = [-2, 1, -3, 4, -1, 2, 1, -5, 4];
296/// assert_eq!(max_subarray_sum(&arr), 6);  // [4, -1, 2, 1]
297/// ```
298pub fn max_subarray_sum(slice: &[i32]) -> i32 {
299    let mut max_sum = slice[0];
300    let mut current_sum = slice[0];
301    for item in slice.iter().skip(1) {
302        current_sum = max(*item, current_sum + *item);
303        max_sum = max(max_sum, current_sum);
304    }
305    max_sum
306}
307
308/// 随机打乱数组/Randomly shuffle array (Fisher-Yates算法/Fisher-Yates algorithm)
309/// 
310/// # 参数/Arguments
311/// * `slice` - 要打乱的数组/Array to shuffle
312/// * `rng` - 随机数生成器实例/Random number generator instance
313/// 
314/// # 示例/Examples
315/// ```
316/// use slice_reducer::shuffle;
317/// use rand::thread_rng;
318/// 
319/// let mut arr = [1, 2, 3, 4, 5];
320/// let mut rng = thread_rng();
321/// shuffle(&mut arr, &mut rng);
322/// println!("{:?}", arr);  // 随机顺序/Random order
323/// ```
324/// 
325/// # 高级用法/Advanced usage
326/// ```
327/// // 使用确定性随机源测试(需rand::rngs::mock)
328/// # #[cfg(feature = "rand")]
329/// use rand::rngs::mock::StepRng;
330/// # #[cfg(feature = "rand")]
331/// let mut test_arr = [1, 2, 3];
332/// # #[cfg(feature = "rand")]
333/// shuffle(&mut test_arr, &mut StepRng::new(0, 1));
334/// # #[cfg(feature = "rand")]
335/// assert_eq!(test_arr, [2, 1, 3]);
336/// ```
337pub fn shuffle<T, R: Rng>(slice: &mut [T], rng: &mut R) {
338    for i in (1..slice.len()).rev() {
339        let j = rng.random_range(0..=i);
340        slice.swap(i, j);
341    }
342}
343
344/// 已排序数组去重/Remove duplicates from sorted array
345/// 
346/// # 参数/Arguments
347/// * `slice` - 要处理的数组(必须已排序)/Array to process (must be sorted)
348/// 
349/// # 示例/Examples
350/// ```
351/// use slice_reducer::dedup_sorted;
352/// let mut arr = vec![1, 1, 2, 3, 3, 3];
353/// dedup_sorted(&mut arr);
354/// assert_eq!(arr, [1, 2, 3]);
355/// ```
356pub fn dedup_sorted<T>(slice: &mut Vec<T>)
357where
358    T: PartialEq + Copy,
359{
360    if slice.is_empty() {
361        return;
362    }
363
364    let mut write_index = 1;
365    for read_index in 1..slice.len() {
366        if slice[read_index] != slice[write_index - 1] {
367            slice[write_index] = slice[read_index];
368            write_index += 1;
369        }
370    }
371    slice.truncate(write_index);
372}
373
374/// 切片比较(类似字典序)/Slice comparison (lexicographical order)
375/// 
376/// # 参数/Arguments
377/// * `a` - 第一个切片/First slice
378/// * `b` - 第二个切片/Second slice
379/// 
380/// # 返回值/Returns
381/// 比较结果(Ordering)/Comparison result (Ordering)
382/// 
383/// # 示例/Examples
384/// ```
385/// use slice_reducer::slice_cmp;
386/// use std::cmp::Ordering;
387/// let a = [1, 2, 3];
388/// let b = [1, 2, 4];
389/// assert_eq!(slice_cmp(&a, &b), Ordering::Less);
390/// ```
391pub fn slice_cmp<T>(a: &[T], b: &[T]) -> Ordering
392where T: Ord
393{
394    let min_len = min(a.len(), b.len());
395    for i in 0..min_len {
396        match a[i].cmp(&b[i]) {
397            Ordering::Less => return Ordering::Less,
398            Ordering::Greater => return Ordering::Greater,
399            Ordering::Equal => continue,
400        }
401    }
402    a.len().cmp(&b.len())
403}
404
405/// 用模式重复填充数组/Repeat pattern to fill array
406/// 
407/// # 参数/Arguments
408/// * `slice` - 要填充的数组/Array to fill
409/// * `pattern` - 重复模式/Pattern to repeat
410/// 
411/// # 示例/Examples
412/// ```
413/// use slice_reducer::repeat_fill;
414/// let mut arr = [0; 5];
415/// repeat_fill(&mut arr, &[1, 2]);
416/// assert_eq!(arr, [1, 2, 1, 2, 1]);
417/// ```
418pub fn repeat_fill<T>(slice: &mut [T], pattern: &[T])
419where T: Copy
420{
421    if pattern.is_empty() {
422        return;
423    }
424    for i in (0..slice.len()).step_by(pattern.len()) {
425        let end = min(i + pattern.len(), slice.len());
426        slice[i..end].copy_from_slice(pattern);
427    }
428}
429
430/// 安全的分割切片/Safely split slice at index
431/// 
432/// # 参数/Arguments
433/// * `slice` - 要分割的切片/Slice to split
434/// * `mid` - 分割位置/Split position
435/// 
436/// # 返回值/Returns
437/// `Some((left, right))` 如果分割成功,否则 `None`/`Some((left, right))` if valid, else `None`
438/// 
439/// # 示例/Examples
440/// ```
441/// use slice_reducer::split_at_checked;
442/// let arr = [1, 2, 3, 4];
443/// assert!(split_at_checked(&arr, 2).is_some());
444/// assert!(split_at_checked(&arr, 5).is_none());
445/// ```
446pub fn split_at_checked<T> (slice: &[T], mid: usize) -> Option<(&[T], &[T])> { 
447    if mid > slice.len() {
448        return None;
449    }
450    Some(slice.split_at(mid))
451}