Могу ли я добавить элементы подвектора в векторе к другому подвектору в том же векторе?

Я пишу код, в котором я хочу сохранить векторы в большем векторе. Позже я хочу добавить значения одного из векторов к другому и удалить вектор, значения которого я передал.

Я сделал две попытки, обе потерпели неудачу, и я был бы очень признателен, если бы кто-нибудь помог мне с этим!

Код, который я использую, выглядит так:

fn my_func(distribution: (u16, u8, u8, u8, u8, u8)) {
    let mut covered: Vec<(Vec<usize>, u16)> = vec![
        (vec![0], distribution.1.into()),
        (vec![1], distribution.2.into()),
        (vec![2], distribution.3.into()),
        (vec![3], distribution.4.into()),
        (vec![4], distribution.5.into()),
    ];

    // Attempt 1 - Error: borrowed as mutable more than once
    &covered[0].0.append(&mut covered[1].0);

    // Attempt 2 - Error: borrowed as mutable and immutable
    for i in &covered[1].0 {
        &covered[0].0.push(*i);
    }
}

Я относительно новичок в Rust, поэтому я все еще изучаю тонкости заимствования. Может ли кто-нибудь помочь мне понять, как мне достичь того, чего я хочу достичь? Любые другие замечания о моем стиле кодирования или других ошибках, которые я допустил, также очень приветствуются.

Что именно вы пытаетесь сделать здесь? Даже если вы не получите ошибок проверки заимствования, типы не будут совпадать. covered[0].0 — это Vec<usize>, в то время как covered[1].0 также является Vec<usize>, вы не можете просто добавить его как элемент. Если вы хотите добавить все элементы из covered[1].0 в covered[0].0, используйте extend_from_slice. Кроме того, синтаксис &a.b — это не (&a).b, а &(a.b), поэтому ваша ведущая ссылка бессмысленна.

Aplet123 21.12.2020 01:32

Даже если бы это был правильный синтаксис (&mut covered[0].0).append(...), вам нужен &mut, чтобы мутировать вектор), это было бы бессмысленно, так как приведение deref в Rust автоматически добавит его.

Aplet123 21.12.2020 01:32

Благодарю за ваш ответ! Я действительно хочу добавить все элементы covered[1].0 к covered[0].0. Боюсь, ваш отзыв слишком высокого уровня, чтобы я мог его понять. Может быть, вы попытаетесь объяснить это проще? Может быть, с примером для правильного ответа.

V.Molotov 21.12.2020 01:45
Почему Python в конце концов умрет
Почему Python в конце концов умрет
Последние 20 лет были действительно хорошими для Python. Он прошел путь от "просто языка сценариев" до основного языка, используемого для написания...
0
3
237
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Предполагая, что я правильно понимаю, что вы пытаетесь сделать. Затем вы пытаетесь изменчиво заимствовать у covered по двум разным индексам. Ваш подход не работает, так как covered[0] приводит к изменчивому заимствованию всего Vec. Вы можете получить только 1 изменяемую ссылку, поэтому последующая covered[1] приводит к ошибке.

Одним из решений для достижения того, что вы пытаетесь, является использование split_at_mut(). Затем вы можете получить 2 изменяемых фрагмента из covered, каждый из которых затем может быть проиндексирован.

Это связано с тем, что известно как «Разделение займов».

fn func(distribution: (u16, u8, u8, u8, u8, u8)) {
    let mut covered: Vec<(Vec<usize>, u16)> = vec![
        (vec![0], distribution.1.into()),
        (vec![1], distribution.2.into()),
        (vec![2], distribution.3.into()),
        (vec![3], distribution.4.into()),
        (vec![4], distribution.5.into()),
    ];

    let (left, right) = covered.split_at_mut(1);

    let v0 = &mut left[0];
    let v1 = &mut right[0];

    // Now both this
    v0.0.append(&mut v1.0);

    // and this works
    for i in &v1.0 {
        v0.0.push(*i);
    }
}

Обратите внимание, что, как упоминалось в комментариях Aplet123, append() перемещает все элементы из otherVec, оставляя его пустым. Если вы не хотите, чтобы otherVec очищался, то вместо этого используйте extend() или extend_from_slice().


Если вы заранее знаете, что можете удалить предмет из списка Vec. Тогда вам не нужно использовать split_at_mut() для этого случая. Затем вы можете сделать, как упомянул RedBorg, и просто remove() предмет и позаимствовать, как вы это сделали бы в противном случае.

fn my_func(distribution: (u16, u8, u8, u8, u8, u8)) {
    let mut covered: Vec<(Vec<usize>, u16)> = vec![
        (vec![0], distribution.1.into()),
        (vec![1], distribution.2.into()),
        (vec![2], distribution.3.into()),
        (vec![3], distribution.4.into()),
        (vec![4], distribution.5.into()),
    ];

    let mut v1 = covered.remove(1);
    let v0 = &mut covered[0];

    // Now both this
    v0.0.append(&mut v1.0);

    // and this works
    for i in &v1.0 {
        v0.0.push(*i);
    }
}

Компилятор перестал кричать! Ты герой!! Однако я не уверен, что это работает. Чтобы проверить это, мне нужно будет удалить теперь избыточную версию v1 из Covered. Все еще ищу способ сделать это. Но все равно большое спасибо за помощь!

V.Molotov 21.12.2020 02:01

Вы имеете в виду удалить весь кортеж (Vec<usize>, u16)? Потому что если это так, то вы можете легко сделать covered.remove(1); после всего остального :)

vallentin 21.12.2020 02:11

Я действительно хочу удалить кортеж. Будет ли Cover.remove(1) удалять по индексу 1? Я думал, что это выскочило 1 предмет из спины. Как-то глупо оглядываться назад. :)

V.Molotov 21.12.2020 02:15

Да, remove() удаляет элемент по указанному индексу. В то время как pop() удаляет последний элемент из Vec

vallentin 21.12.2020 02:18

Ты мой герой! Спасибо за помощь и с наступающими праздниками!

V.Molotov 21.12.2020 02:19

Пожалуйста, рада, что смогла помочь, и вас тоже с праздником! :)

vallentin 21.12.2020 02:23

@ В.Молотов Вы хотите удалить кортеж из covered и добавить вектор этого удаленного элемента в другой подвектор? Потому что тогда очень легко удалить кортежи (которые передают его право собственности на вашу область), взять его вектор и добавить его к новому. Обратите внимание, что это изменит индексы. covered[0].0.append(&mut covered.remove(1).0)

RedBorg 21.12.2020 03:46

Конкретный пример, который дал RedBorg, не работает, так как вам нужно remove() перед заимствованием covered. Тем не менее, предпосылка по-прежнему работает, и я обновил ответ, включив в него пример.

vallentin 21.12.2020 16:18

Другие вопросы по теме