< 返回版块

githik999 发表于 2022-06-16 18:50

假设 我有一个 vec 或者 array

现在我想把这个容器平均拆成两半

这里必须按照隔1拆的方式 而不能是分前面一半 后面一半

也就是 单数index的一半 双数index的另外一半

怎么搞比较合理

现在只能想到循环

大家有没有什么其他写法 欢迎贴代码

评论区

写评论
作者 githik999 2022-06-19 14:11

的确 没必要搞这个复杂的

--
👇
7sDream: 可以看下 Iterator 的 partition 方法。

但是这个如果要根据 index 分组的话需要先 enumerate,但是 partition 后面又不能再 map 了,可能也不是非常满足需求。

如果非要弄,可以搞一个辅助类型:

#[derive(Debug, Default, PartialEq, Eq, PartialOrd, Ord, Clone)]
struct Part<T> {
    pub inner: Vec<T>
}

impl<T> Extend<(usize, T)> for Part<T> {
    fn extend<I>(&mut self, iter: I)
    where I: IntoIterator<Item = (usize, T)> {
        self.inner.extend(iter.into_iter().map(|(_, v)| v))
    }
}

fn main() {
    let v = vec![0, 1, 2, 3, 4, 5, 6, 7];

    let (odd, even): (Part<_>, Part<_>) = v
        .into_iter()
        .enumerate()
        .partition(|(i, _)| i % 2 == 0);

    println!("odd: {odd:?}, even: {even:?}")
}
odd: Part { inner: [0, 2, 4, 6] }, even: Part { inner: [1, 3, 5, 7] }

但这样好像感觉,还不如写循环算了呢……

作者 githik999 2022-06-19 14:10

这种其实跟自己循环然后if else判断是不是一样的..

--
👇
苦瓜小仔: 为什么不直接这样:

fn main() {
    let v = vec![0, 1, 2, 3, 4];
    let mut idx = 0;
    let (a, b): (Vec<_>, Vec<_>) = v.into_iter().partition(|_| {
        idx += 1;
        idx % 2 != 0
    });
    dbg!(a, b);
}
作者 githik999 2022-06-19 14:09

这种单个循环也行 但是循环里面要每个取模if else判断.不确定跟双循环哪个好

--
👇
Neutron3529: 感觉你可能需要一个rayon

use rayon::iter::Either;
use rayon::prelude::*;
use std::thread::sleep_ms;
fn main() {
    let (mut left, right): (Vec<_>, Vec<_>) = (0..40000)
        .into_par_iter()
        .map(|x| {
            sleep_ms(1);
            if x % 2 == 0 {
                Either::Left(x/2)
            } else {
                Either::Right(x/2)
            }
        })
        .collect();
    dbg!(left == right);
    left.sort();
    dbg!(left == right);
}

可以看出,耗时大概是按双线程计算的(额外开销不知为何略大,但基本还算正常)

[src/main.rs:17] now.elapsed() = 2.664248124s
[src/main.rs:18] left == right = true
[src/main.rs:20] left == right = true
作者 githik999 2022-06-19 14:02

我现在就是这样做的 优点是代码简单很容易看出作者意思 缺点是两次循环

我不确定 两个步长为2的循环 和 一个步长为1的循环

耗时是不是一样的

--
👇
chirsz-ever: ``` fn main() { let v = vec![1, 2, 3, 4, 5, 6]; let v0 = v.iter().step_by(2).collect::<Vec<_>>(); let v1 = v.iter().skip(1).step_by(2).collect::<Vec<_>>(); dbg!(v0); dbg!(v1); }


chirsz-ever 2022-06-17 02:02
fn main() {
    let v = vec![1, 2, 3, 4, 5, 6];
    let v0 = v.iter().step_by(2).collect::<Vec<_>>();
    let v1 = v.iter().skip(1).step_by(2).collect::<Vec<_>>();
    dbg!(v0);
    dbg!(v1);
}
Neutron3529 2022-06-16 21:39

感觉你可能需要一个rayon

use rayon::iter::Either;
use rayon::prelude::*;
use std::thread::sleep_ms;
fn main() {
    let (mut left, right): (Vec<_>, Vec<_>) = (0..40000)
        .into_par_iter()
        .map(|x| {
            sleep_ms(1);
            if x % 2 == 0 {
                Either::Left(x/2)
            } else {
                Either::Right(x/2)
            }
        })
        .collect();
    dbg!(left == right);
    left.sort();
    dbg!(left == right);
}

可以看出,耗时大概是按双线程计算的(额外开销不知为何略大,但基本还算正常)

[src/main.rs:17] now.elapsed() = 2.664248124s
[src/main.rs:18] left == right = true
[src/main.rs:20] left == right = true
苦瓜小仔 2022-06-16 21:08

为什么不直接这样:

fn main() {
    let v = vec![0, 1, 2, 3, 4];
    let mut idx = 0;
    let (a, b): (Vec<_>, Vec<_>) = v.into_iter().partition(|_| {
        idx += 1;
        idx % 2 != 0
    });
    dbg!(a, b);
}
7sDream 2022-06-16 21:04

可以看下 Iterator 的 partition 方法。

但是这个如果要根据 index 分组的话需要先 enumerate,但是 partition 后面又不能再 map 了,可能也不是非常满足需求。

如果非要弄,可以搞一个辅助类型:

#[derive(Debug, Default, PartialEq, Eq, PartialOrd, Ord, Clone)]
struct Part<T> {
    pub inner: Vec<T>
}

impl<T> Extend<(usize, T)> for Part<T> {
    fn extend<I>(&mut self, iter: I)
    where I: IntoIterator<Item = (usize, T)> {
        self.inner.extend(iter.into_iter().map(|(_, v)| v))
    }
}

fn main() {
    let v = vec![0, 1, 2, 3, 4, 5, 6, 7];

    let (odd, even): (Part<_>, Part<_>) = v
        .into_iter()
        .enumerate()
        .partition(|(i, _)| i % 2 == 0);

    println!("odd: {odd:?}, even: {even:?}")
}
odd: Part { inner: [0, 2, 4, 6] }, even: Part { inner: [1, 3, 5, 7] }

但这样好像感觉,还不如写循环算了呢……

1 共 8 条评论, 1 页