Я пишу код, в котором я хочу сохранить векторы в большем векторе. Позже я хочу добавить значения одного из векторов к другому и удалить вектор, значения которого я передал.
Я сделал две попытки, обе потерпели неудачу, и я был бы очень признателен, если бы кто-нибудь помог мне с этим!
Код, который я использую, выглядит так:
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, поэтому я все еще изучаю тонкости заимствования. Может ли кто-нибудь помочь мне понять, как мне достичь того, чего я хочу достичь? Любые другие замечания о моем стиле кодирования или других ошибках, которые я допустил, также очень приветствуются.
Даже если бы это был правильный синтаксис (&mut covered[0].0).append(...)
, вам нужен &mut
, чтобы мутировать вектор), это было бы бессмысленно, так как приведение deref в Rust автоматически добавит его.
Благодарю за ваш ответ! Я действительно хочу добавить все элементы covered[1].0
к covered[0].0
. Боюсь, ваш отзыв слишком высокого уровня, чтобы я мог его понять. Может быть, вы попытаетесь объяснить это проще? Может быть, с примером для правильного ответа.
Предполагая, что я правильно понимаю, что вы пытаетесь сделать. Затем вы пытаетесь изменчиво заимствовать у 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() перемещает все элементы из other
Vec
, оставляя его пустым. Если вы не хотите, чтобы other
Vec
очищался, то вместо этого используйте 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. Все еще ищу способ сделать это. Но все равно большое спасибо за помощь!
Вы имеете в виду удалить весь кортеж (Vec<usize>, u16)
? Потому что если это так, то вы можете легко сделать covered.remove(1);
после всего остального :)
Я действительно хочу удалить кортеж. Будет ли Cover.remove(1) удалять по индексу 1? Я думал, что это выскочило 1 предмет из спины. Как-то глупо оглядываться назад. :)
Да, remove() удаляет элемент по указанному индексу. В то время как pop() удаляет последний элемент из Vec
Ты мой герой! Спасибо за помощь и с наступающими праздниками!
Пожалуйста, рада, что смогла помочь, и вас тоже с праздником! :)
@ В.Молотов Вы хотите удалить кортеж из covered
и добавить вектор этого удаленного элемента в другой подвектор? Потому что тогда очень легко удалить кортежи (которые передают его право собственности на вашу область), взять его вектор и добавить его к новому. Обратите внимание, что это изменит индексы. covered[0].0.append(&mut covered.remove(1).0)
Конкретный пример, который дал RedBorg, не работает, так как вам нужно remove()
перед заимствованием covered
. Тем не менее, предпосылка по-прежнему работает, и я обновил ответ, включив в него пример.
Что именно вы пытаетесь сделать здесь? Даже если вы не получите ошибок проверки заимствования, типы не будут совпадать.
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)
, поэтому ваша ведущая ссылка бессмысленна.