22次重大版本更新

52.2.0 2024年7月28日
52.0.0 2024年6月6日
51.0.0 2024年3月18日
50.0.0 2024年1月12日
30.0.1 2023年1月8日

#221文本处理

Download history 148399/week @ 2024-04-17 157325/week @ 2024-04-24 137158/week @ 2024-05-01 156889/week @ 2024-05-08 152699/week @ 2024-05-15 151627/week @ 2024-05-22 194067/week @ 2024-05-29 257407/week @ 2024-06-05 248922/week @ 2024-06-12 239154/week @ 2024-06-19 295884/week @ 2024-06-26 236272/week @ 2024-07-03 256527/week @ 2024-07-10 250157/week @ 2024-07-17 266141/week @ 2024-07-24 270408/week @ 2024-07-31

1,098,120 每月下载量
294 个 crates 中使用 (直接使用 6 个)

Apache-2.0

2MB
38K SLoC

集合的类似行向表示,其中包含 Array

[Row]s 被归一化以进行排序,因此可以使用 memcmp 在底层高效地比较,或在 非比较排序(如 基数排序)中使用,这使得行格式非常适合实现高效的列排序、分组、聚合、窗口化等,如这篇博客文章中所述。

例如,给定三个输入 ArrayRowConverter 创建的字节序列与使用 lexsort 相同。

   ┌─────┐   ┌─────┐   ┌─────┐
   │     │   │     │   │     │
   ├─────┤ ┌ ┼─────┼ ─ ┼─────┼ ┐              ┏━━━━━━━━━━━━━┓
   │     │   │     │   │     │  ─────────────▶┃             ┃
   ├─────┤ └ ┼─────┼ ─ ┼─────┼ ┘              ┗━━━━━━━━━━━━━┛
   │     │   │     │   │     │
   └─────┘   └─────┘   └─────┘
               ...
   ┌─────┐ ┌ ┬─────┬ ─ ┬─────┬ ┐              ┏━━━━━━━━┓
   │     │   │     │   │     │  ─────────────▶┃        ┃
   └─────┘ └ ┴─────┴ ─ ┴─────┴ ┘              ┗━━━━━━━━┛
    UInt64      Utf8     F64

          Input Arrays                          Row Format
    (Columns)

Rows 必须由相同的 RowConverter 生成,才能进行有意义的比较。

基本示例


let a1 = Arc::new(Int32Array::from_iter_values([-1, -1, 0, 3, 3])) as ArrayRef;
let a2 = Arc::new(StringArray::from_iter_values(["a", "b", "c", "d", "d"])) as ArrayRef;
let arrays = vec![a1, a2];

// Convert arrays to rows
let converter = RowConverter::new(vec![
    SortField::new(DataType::Int32),
    SortField::new(DataType::Utf8),
]).unwrap();
let rows = converter.convert_columns(&arrays).unwrap();

// Compare rows
for i in 0..4 {
    assert!(rows.row(i) <= rows.row(i + 1));
}
assert_eq!(rows.row(3), rows.row(4));

// Convert rows back to arrays
let converted = converter.convert_rows(&rows).unwrap();
assert_eq!(arrays, converted);

// Compare rows from different arrays
let a1 = Arc::new(Int32Array::from_iter_values([3, 4])) as ArrayRef;
let a2 = Arc::new(StringArray::from_iter_values(["e", "f"])) as ArrayRef;
let arrays = vec![a1, a2];
let rows2 = converter.convert_columns(&arrays).unwrap();

assert!(rows.row(4) < rows2.row(0));
assert!(rows.row(4) < rows2.row(1));

// Convert selection of rows back to arrays
let selection = [rows.row(0), rows2.row(1), rows.row(2), rows2.row(0)];
let converted = converter.convert_rows(selection).unwrap();
let c1 = converted[0].as_primitive::<Int32Type>();
assert_eq!(c1.values(), &[-1, 4, 0, 3]);

let c2 = converted[1].as_string::<i32>();
let c2_values: Vec<_> = c2.iter().flatten().collect();
assert_eq!(&c2_values, &["a", "f", "c", "e"]);

Lexsort

行格式还可以用于实现快速的多列/字典序排序

fn lexsort_to_indices(arrays: &[ArrayRef]) -> UInt32Array {
    let fields = arrays
        .iter()
        .map(|a| SortField::new(a.data_type().clone()))
        .collect();
    let converter = RowConverter::new(fields).unwrap();
    let rows = converter.convert_columns(arrays).unwrap();
    let mut sort: Vec<_> = rows.iter().enumerate().collect();
    sort.sort_unstable_by(|(_, a), (_, b)| a.cmp(b));
    UInt32Array::from_iter_values(sort.iter().map(|(i, _)| *i as u32))
}

依赖项

~2.8–9MB
~69K SLoC