Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
1af42261
R
Rust
项目概览
int
/
Rust
大约 1 年 前同步成功
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
Rust
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
1af42261
编写于
7月 14, 2017
作者:
A
Alexis Beingessner
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Add Vec::drain_filter
上级
ae4803a7
变更
3
显示空白变更内容
内联
并排
Showing
3 changed file
with
281 addition
and
0 deletion
+281
-0
src/liballoc/tests/lib.rs
src/liballoc/tests/lib.rs
+1
-0
src/liballoc/tests/vec.rs
src/liballoc/tests/vec.rs
+167
-0
src/liballoc/vec.rs
src/liballoc/vec.rs
+113
-0
未找到文件。
src/liballoc/tests/lib.rs
浏览文件 @
1af42261
...
...
@@ -16,6 +16,7 @@
#![feature(inclusive_range_syntax)]
#![feature(collection_placement)]
#![feature(const_fn)]
#![feature(drain_filter)]
#![feature(exact_size_is_empty)]
#![feature(iterator_step_by)]
#![feature(pattern)]
...
...
src/liballoc/tests/vec.rs
浏览文件 @
1af42261
...
...
@@ -801,3 +801,170 @@ fn overaligned_allocations() {
assert
!
(
v
.as_ptr
()
as
usize
&
0xff
==
0
);
}
}
#[test]
fn
drain_filter_empty
()
{
let
mut
vec
:
Vec
<
i32
>
=
vec!
[];
{
let
mut
iter
=
vec
.drain_filter
(|
_
|
true
);
assert_eq!
(
iter
.size_hint
(),
(
0
,
Some
(
0
)));
assert_eq!
(
iter
.next
(),
None
);
assert_eq!
(
iter
.size_hint
(),
(
0
,
Some
(
0
)));
assert_eq!
(
iter
.next
(),
None
);
assert_eq!
(
iter
.size_hint
(),
(
0
,
Some
(
0
)));
}
assert_eq!
(
vec
.len
(),
0
);
assert_eq!
(
vec
,
vec!
[]);
}
#[test]
fn
drain_filter_zst
()
{
let
mut
vec
=
vec!
[(),
(),
(),
(),
()];
let
initial_len
=
vec
.len
();
let
mut
count
=
0
;
{
let
mut
iter
=
vec
.drain_filter
(|
_
|
true
);
assert_eq!
(
iter
.size_hint
(),
(
0
,
Some
(
initial_len
)));
while
let
Some
(
_
)
=
iter
.next
()
{
count
+=
1
;
assert_eq!
(
iter
.size_hint
(),
(
0
,
Some
(
initial_len
-
count
)));
}
assert_eq!
(
iter
.size_hint
(),
(
0
,
Some
(
0
)));
assert_eq!
(
iter
.next
(),
None
);
assert_eq!
(
iter
.size_hint
(),
(
0
,
Some
(
0
)));
}
assert_eq!
(
count
,
initial_len
);
assert_eq!
(
vec
.len
(),
0
);
assert_eq!
(
vec
,
vec!
[]);
}
#[test]
fn
drain_filter_false
()
{
let
mut
vec
=
vec!
[
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
,
9
,
10
];
let
initial_len
=
vec
.len
();
let
mut
count
=
0
;
{
let
mut
iter
=
vec
.drain_filter
(|
_
|
false
);
assert_eq!
(
iter
.size_hint
(),
(
0
,
Some
(
initial_len
)));
for
_
in
iter
.by_ref
()
{
count
+=
1
;
}
assert_eq!
(
iter
.size_hint
(),
(
0
,
Some
(
0
)));
assert_eq!
(
iter
.next
(),
None
);
assert_eq!
(
iter
.size_hint
(),
(
0
,
Some
(
0
)));
}
assert_eq!
(
count
,
0
);
assert_eq!
(
vec
.len
(),
initial_len
);
assert_eq!
(
vec
,
vec!
[
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
,
9
,
10
]);
}
#[test]
fn
drain_filter_true
()
{
let
mut
vec
=
vec!
[
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
,
9
,
10
];
let
initial_len
=
vec
.len
();
let
mut
count
=
0
;
{
let
mut
iter
=
vec
.drain_filter
(|
_
|
true
);
assert_eq!
(
iter
.size_hint
(),
(
0
,
Some
(
initial_len
)));
while
let
Some
(
_
)
=
iter
.next
()
{
count
+=
1
;
assert_eq!
(
iter
.size_hint
(),
(
0
,
Some
(
initial_len
-
count
)));
}
assert_eq!
(
iter
.size_hint
(),
(
0
,
Some
(
0
)));
assert_eq!
(
iter
.next
(),
None
);
assert_eq!
(
iter
.size_hint
(),
(
0
,
Some
(
0
)));
}
assert_eq!
(
count
,
initial_len
);
assert_eq!
(
vec
.len
(),
0
);
assert_eq!
(
vec
,
vec!
[]);
}
#[test]
fn
drain_filter_complex
()
{
{
// [+xxx++++++xxxxx++++x+x++]
let
mut
vec
=
vec!
[
1
,
2
,
4
,
6
,
7
,
9
,
11
,
13
,
15
,
17
,
18
,
20
,
22
,
24
,
26
,
27
,
29
,
31
,
33
,
34
,
35
,
36
,
37
,
39
];
let
removed
=
vec
.drain_filter
(|
x
|
*
x
%
2
==
0
)
.collect
::
<
Vec
<
_
>>
();
assert_eq!
(
removed
.len
(),
10
);
assert_eq!
(
removed
,
vec!
[
2
,
4
,
6
,
18
,
20
,
22
,
24
,
26
,
34
,
36
]);
assert_eq!
(
vec
.len
(),
14
);
assert_eq!
(
vec
,
vec!
[
1
,
7
,
9
,
11
,
13
,
15
,
17
,
27
,
29
,
31
,
33
,
35
,
37
,
39
]);
}
{
// [xxx++++++xxxxx++++x+x++]
let
mut
vec
=
vec!
[
2
,
4
,
6
,
7
,
9
,
11
,
13
,
15
,
17
,
18
,
20
,
22
,
24
,
26
,
27
,
29
,
31
,
33
,
34
,
35
,
36
,
37
,
39
];
let
removed
=
vec
.drain_filter
(|
x
|
*
x
%
2
==
0
)
.collect
::
<
Vec
<
_
>>
();
assert_eq!
(
removed
.len
(),
10
);
assert_eq!
(
removed
,
vec!
[
2
,
4
,
6
,
18
,
20
,
22
,
24
,
26
,
34
,
36
]);
assert_eq!
(
vec
.len
(),
13
);
assert_eq!
(
vec
,
vec!
[
7
,
9
,
11
,
13
,
15
,
17
,
27
,
29
,
31
,
33
,
35
,
37
,
39
]);
}
{
// [xxx++++++xxxxx++++x+x]
let
mut
vec
=
vec!
[
2
,
4
,
6
,
7
,
9
,
11
,
13
,
15
,
17
,
18
,
20
,
22
,
24
,
26
,
27
,
29
,
31
,
33
,
34
,
35
,
36
];
let
removed
=
vec
.drain_filter
(|
x
|
*
x
%
2
==
0
)
.collect
::
<
Vec
<
_
>>
();
assert_eq!
(
removed
.len
(),
10
);
assert_eq!
(
removed
,
vec!
[
2
,
4
,
6
,
18
,
20
,
22
,
24
,
26
,
34
,
36
]);
assert_eq!
(
vec
.len
(),
11
);
assert_eq!
(
vec
,
vec!
[
7
,
9
,
11
,
13
,
15
,
17
,
27
,
29
,
31
,
33
,
35
]);
}
{
// [xxxxxxxxxx+++++++++++]
let
mut
vec
=
vec!
[
2
,
4
,
6
,
8
,
10
,
12
,
14
,
16
,
18
,
20
,
1
,
3
,
5
,
7
,
9
,
11
,
13
,
15
,
17
,
19
];
let
removed
=
vec
.drain_filter
(|
x
|
*
x
%
2
==
0
)
.collect
::
<
Vec
<
_
>>
();
assert_eq!
(
removed
.len
(),
10
);
assert_eq!
(
removed
,
vec!
[
2
,
4
,
6
,
8
,
10
,
12
,
14
,
16
,
18
,
20
]);
assert_eq!
(
vec
.len
(),
10
);
assert_eq!
(
vec
,
vec!
[
1
,
3
,
5
,
7
,
9
,
11
,
13
,
15
,
17
,
19
]);
}
{
// [+++++++++++xxxxxxxxxx]
let
mut
vec
=
vec!
[
1
,
3
,
5
,
7
,
9
,
11
,
13
,
15
,
17
,
19
,
2
,
4
,
6
,
8
,
10
,
12
,
14
,
16
,
18
,
20
];
let
removed
=
vec
.drain_filter
(|
x
|
*
x
%
2
==
0
)
.collect
::
<
Vec
<
_
>>
();
assert_eq!
(
removed
.len
(),
10
);
assert_eq!
(
removed
,
vec!
[
2
,
4
,
6
,
8
,
10
,
12
,
14
,
16
,
18
,
20
]);
assert_eq!
(
vec
.len
(),
10
);
assert_eq!
(
vec
,
vec!
[
1
,
3
,
5
,
7
,
9
,
11
,
13
,
15
,
17
,
19
]);
}
}
src/liballoc/vec.rs
浏览文件 @
1af42261
...
...
@@ -1960,6 +1960,65 @@ pub fn splice<R, I>(&mut self, range: R, replace_with: I) -> Splice<I::IntoIter>
}
}
/// Creates an iterator which uses a closure to determine if an element should be removed.
///
/// If the closure returns true, then the element is removed and yielded.
/// If the closure returns false, it will try again, and call the closure
/// on the next element, seeing if it passes the test.
///
/// Using this method is equivalent to the following code:
///
/// ```
/// # let some_predicate = |x: &mut i32| { *x == 2 };
/// # let mut vec = vec![1, 2, 3, 4, 5];
/// let mut i = 0;
/// while i != vec.len() {
/// if some_predicate(&mut vec[i]) {
/// let val = vec.remove(i);
/// // your code here
/// }
/// i += 1;
/// }
/// ```
///
/// But `drain_filter` is easier to use. `drain_filter` is also more efficient,
/// because it can backshift the elements of the array in bulk.
///
/// Note that `drain_filter` also lets you mutate every element in the filter closure,
/// regardless of whether you choose to keep or remove it.
///
///
/// # Examples
///
/// Splitting an array into evens and odds, reusing the original allocation:
///
/// ```
/// #![feature(drain_filter)]
/// let mut numbers = vec![1, 2, 3, 4, 5, 6, 8, 9, 11, 13, 14, 15];
///
/// let evens = numbers.drain_filter(|x| *x % 2 == 0).collect::<Vec<_>>();
/// let odds = numbers;
///
/// assert_eq!(evens, vec![2, 4, 6, 8, 14]);
/// assert_eq!(odds, vec![1, 3, 5, 9, 11, 13, 15]);
/// ```
#[unstable(feature
=
"drain_filter"
,
reason
=
"recently added"
,
issue
=
"43244"
)]
pub
fn
drain_filter
<
F
>
(
&
mut
self
,
filter
:
F
)
->
DrainFilter
<
T
,
F
>
where
F
:
FnMut
(
&
mut
T
)
->
bool
,
{
let
old_len
=
self
.len
();
// Guard against us getting leaked (leak amplification)
unsafe
{
self
.set_len
(
0
);
}
DrainFilter
{
vec
:
self
,
idx
:
0
,
del
:
0
,
old_len
,
pred
:
filter
,
}
}
}
#[stable(feature
=
"extend_ref"
,
since
=
"1.2.0"
)]
...
...
@@ -2596,3 +2655,57 @@ unsafe fn move_tail(&mut self, extra_capacity: usize) {
self
.tail_start
=
new_tail_start
;
}
}
/// An iterator produced by calling `drain_filter` on Vec.
#[unstable(feature
=
"drain_filter"
,
reason
=
"recently added"
,
issue
=
"43244"
)]
#[derive(Debug)]
pub
struct
DrainFilter
<
'a
,
T
:
'a
,
F
>
where
F
:
FnMut
(
&
mut
T
)
->
bool
,
{
vec
:
&
'a
mut
Vec
<
T
>
,
idx
:
usize
,
del
:
usize
,
old_len
:
usize
,
pred
:
F
,
}
#[unstable(feature
=
"drain_filter"
,
reason
=
"recently added"
,
issue
=
"43244"
)]
impl
<
'a
,
T
,
F
>
Iterator
for
DrainFilter
<
'a
,
T
,
F
>
where
F
:
FnMut
(
&
mut
T
)
->
bool
,
{
type
Item
=
T
;
fn
next
(
&
mut
self
)
->
Option
<
T
>
{
unsafe
{
while
self
.idx
!=
self
.old_len
{
let
i
=
self
.idx
;
self
.idx
+=
1
;
let
v
=
slice
::
from_raw_parts_mut
(
self
.vec
.as_mut_ptr
(),
self
.old_len
);
if
(
self
.pred
)(
&
mut
v
[
i
])
{
self
.del
+=
1
;
return
Some
(
ptr
::
read
(
&
v
[
i
]));
}
else
if
self
.del
>
0
{
v
.swap
(
i
-
self
.del
,
i
);
}
}
None
}
}
fn
size_hint
(
&
self
)
->
(
usize
,
Option
<
usize
>
)
{
(
0
,
Some
(
self
.old_len
-
self
.idx
))
}
}
#[unstable(feature
=
"drain_filter"
,
reason
=
"recently added"
,
issue
=
"43244"
)]
impl
<
'a
,
T
,
F
>
Drop
for
DrainFilter
<
'a
,
T
,
F
>
where
F
:
FnMut
(
&
mut
T
)
->
bool
,
{
fn
drop
(
&
mut
self
)
{
for
_
in
self
.by_ref
()
{
}
unsafe
{
self
.vec
.set_len
(
self
.old_len
-
self
.del
);
}
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录