4个版本

0.0.1-release2019年2月12日
0.0.1-preview2019年2月11日

#1472Rust模式

Apache-2.0

30KB
535

Rust中的Linq

Codacy Badge Average time to resolve an issue Percentage of issues still open

在Rust中使用声明性宏创建的语言集成查询

此项目正在开发中! API可能会发生更改。

快速入门

这是一个示例

use linq::linq;
use linq::iter::Enumerable;

fn try_linq_methods() {
    let x = 1..100;
    let mut y: Vec<i32> = x.clone().filter(|p| p <= &5).collect();
    y.sort_by_key(|t| -t);
    let y: Vec<i32> = y.into_iter().map(|t| t * 2).collect();
    let e: Vec<i32> = x
        .clone()
        .where_by(|p| p <= &5)
        .order_by(|p| -p)
        .select(|p| p * 2)
        .collect();
    assert_eq!(e, y);
}

fn try_linq_expr() {
    let x = 1..100;
    let mut y: Vec<i32> = x.clone().filter(|p| p <= &5).collect();
    y.sort_by_key(|t| -t);
    let y: Vec<i32> = y.into_iter().map(|t| t * 2).collect();
    let e: Vec<i32> =
        linq!(from p in x.clone(), where p <= &5, orderby -p, select p * 2).collect();
    assert_eq!(e, y);
}

如果你熟悉C#中的LINQ,你会发现这很容易使用。

用法

这两个导入是必需的

use linq::linq;                 // for `linq!` macro
use linq::iter::Enumerable;     // for LINQ methods and `linq!` macro

方法

特质linq::iter::Enumerable支持在Iterator上使用LINQ方法。以下是一些对应关系。

  • 普通项表示它们是std中Iterator的内置方法。
  • 加粗项表示它们在此项目中实现。您可以在模块linq::iter中找到它们(但它们是私有的,因此您不能导入它们)。
  • 斜体项表示它们不在路线图中。欢迎您的建议。
  • 更多示例请参见这里

  • where => where_by => filter
  • select => map
  • select_many => select_many_single, select_many
  • skip
  • skip_while
  • take
  • take_while
  • join
  • group_join
  • concat => chain
  • order_by
  • order_by_descending
  • then_by
  • then_by_descending
  • reverse => rev
  • group_by
  • distinct
  • union
  • intersect
  • except
  • first => next
  • single
  • element_at => nth
  • all
  • any
  • contains
  • count
  • sum
  • product
  • min
  • max
  • average
  • aggregate => fold

表达式

查询表达式以from子句开始,以select子句结束。使用,分隔每个子句。

linq!(from x in coll, select x)

目前支持以下关键字

  • from
    • from (select_many_single)
    • zfrom (select_many)
  • in
  • select
  • where
  • orderby
  • descending
  • group_by
  • 更多...

来自

from <id> in <iter expr>,

此外,您还可以列出集合中每个集合的元素(注意:对于此类型,您无法访问select子句中第一个from子句中的值)

let x = 1..5;
let y = vec![0, 0, 1, 0, 1, 2, 0, 1, 2, 3];
let e: Vec<i32> = linq!(from p in x.clone(), from t in 0..p, select t).collect();

assert_eq!(e, y);

如果您想压缩或列出两个集合的值对,请使用zfrom作为第二个from

let x = 1..5;
let y = vec![
    (1, 0),
    (2, 0),
    (2, 1),
    (3, 0),
    (3, 1),
    (3, 2),
    (4, 0),
    (4, 1),
    (4, 2),
    (4, 3),
];
let e: Vec<_> = linq!(from p in x.clone(), zfrom t in 0..p, select (p,t)).collect();

assert_eq!(e, y);

zfrom中的表达式接收第一个from中克隆的值,并将两个集合中的元素克隆用于select子句。

位置

where <expr>,

在单个来源查询中,您可以使用where子句。表达式将接收在from子句中命名的变量id。表达式需要返回一个布尔值。

Orderby

orderby <expr>,
orderby <expr>, descending,

在单个来源查询中,您可以使用orderby子句。此查询将收集迭代器,并按表达式排序,然后返回新的迭代器。

开发

我们需要更多的单元测试样本。如果您有任何想法,请创建问题告诉我们。

由于表达式过程宏不稳定,我仅通过声明性宏创建宏。

$ cargo test

没有运行时依赖