Как получить 2 разных изменяемых элемента из вектора одновременно? [Дубликат]

Хотя это не подходит и эффективно использовать регулярные выражения для этой цели, иногда регулярные выражения предоставляют быстрые решения для простых проблем совпадения, и, на мой взгляд, не так уж и сложно использовать регулярные выражения для тривиальных работ.

Существует окончательное сообщение в блоге о совпадении сокровенных HTML-элементов, написанных Стивеном Левитаном.

23
задан Shepmaster 20 February 2017 в 15:10
поделиться

5 ответов

21
ответ дан Shepmaster 5 September 2018 в 15:23
поделиться

Вы не можете сделать две изменяемые ссылки на одни и те же данные. Это явно запрещается средством проверки заимствований, чтобы предотвратить одновременные изменения. Однако вы можете обойти проверку чеков с помощью блоков unsafe.

Хотя в вашем случае v[0] и v[1] явно являются отдельными кусками, это не выдерживает серьезного внимания. Что, если v - это какая-то карта, называемая NullMap, которая отображает все элементы в одно поле? Как известно компилятору в Vec операциях v[0];v[1]; безопасно, но в NullMap нет?


Если вы пытаетесь поменять два элемента массива, почему бы не пойти slice::swap ?

fn main() {
    let mut v = vec![1, 2, 3];
    v.swap(0,1);
    println!("{:?}",v);
}

Также v должен быть mut, потому что вы меняете вектор. Неизменяемая версия будет клонировать и выполнять обмен на нее.

2
ответ дан Daniel Fath 15 August 2018 в 16:18
поделиться

Метод [T]::iter_mut() возвращает итератор, который может дать изменяемую ссылку для каждого элемента в срезе. Другие коллекции также имеют метод iter_mut. Эти методы часто инкапсулируют небезопасный код, но их интерфейс полностью безопасен.

Вот черта расширения общего назначения, которая добавляет метод на срезах, который возвращает изменчивые ссылки на два разных элемента по индексу:

pub trait SliceExt {
    type Item;

    fn get_two_mut(&mut self, index0: usize, index1: usize) -> (&mut Self::Item, &mut Self::Item);
}

impl<T> SliceExt for [T] {
    type Item = T;

    fn get_two_mut(&mut self, index0: usize, index1: usize) -> (&mut Self::Item, &mut Self::Item) {
        match index0.cmp(&index1) {
            Ordering::Less => {
                let mut iter = self.iter_mut();
                let item0 = iter.nth(index0).unwrap();
                let item1 = iter.nth(index1 - index0 - 1).unwrap();
                (item0, item1)
            }
            Ordering::Equal => panic!("[T]::get_two_mut(): received same index twice ({})", index0),
            Ordering::Greater => {
                let mut iter = self.iter_mut();
                let item1 = iter.nth(index1).unwrap();
                let item0 = iter.nth(index0 - index1 - 1).unwrap();
                (item0, item1)
            }
        }
    }
}
3
ответ дан Francis Gagné 15 August 2018 в 16:18
поделиться

Проблема заключается в том, что &mut v[…] сначала с мутностью заимствует v, а затем передает переменную ссылку на элемент на функцию изменения.

Этот комментарий reddit имеет решение вашей проблемы.

Редактировать: Спасибо за хедз-ап, Shepmaster. par-vec - это библиотека, которая позволяет с легкостью брать раздельные разделы vec.

-1
ответ дан llogiq 15 August 2018 в 16:18
поделиться
  • 1
    Пожалуйста, включите решение. Ссылки со временем устаревают. – Shepmaster 6 May 2015 в 11:02

На ночном канале сопоставление образцов может выполняться с помощью срезов. Вы можете использовать это, если у вас нет огромных индексов, и ваши индексы известны во время компиляции.

#![feature(slice_patterns)]

fn change(a: &mut i32, b: &mut i32) {
    let c = *a;
    *a = *b;
    *b = c;
}

fn main() {
    let mut arr = [5, 6, 7, 8];
    {
        let &mut [ref mut a, _, ref mut b, _..] = &mut arr;
        change(a, b);
    }
    assert_eq!(arr, [7, 6, 5, 8]);
}

Обратите внимание, что вам нужно включить функцию slice_patterns.

8
ответ дан Shepmaster 15 August 2018 в 16:18
поделиться
Другие вопросы по тегам:

Похожие вопросы: