Итерация по вектору и приведение перечисления к целому - PullRequest
1 голос
/ 28 мая 2019

У меня есть вектор перечислений, которые я хочу привести к целочисленному значению, чтобы я мог провести численное сравнение.

Я все время сталкиваюсь с предупреждениями о заимствовании "не могу выйти из заимствованного контекста"

Я пробовал различные варианты следующего:

enum SomeEnum {
    A,
    B,
    C,
}

let values = vec![SomeEnum::A, SomeEnum::B];

for val in values.iter() {
  let i = *val as i32;
  // if i < X do something
}

Ответы [ 2 ]

5 голосов
/ 28 мая 2019

Когда вы звоните values.iter(), вы берете ссылку на Vec tor как срез, потому что это impl s Deref<Target=[T]>. Возвращает Iterator сверх &T, который заимствован. Затем попробуйте следующую строку:

let i = *val as i32;

Существует проблема с этим: val имеет тип &SomeEnum, и поэтому вы не можете переместить значение из ссылки, или скопировать его, потому что SomeEnum не подразумевает Copy или Clone. Чтобы решить эту проблему, вы можете выбрать один из следующих вариантов в зависимости от сценария:

  • Copy значение, сделав enum Copy. Выполнение этого приводит к тому, что ржавчина может неявно копировать значение побитово.
#[derive(Copy)]
enum SomeEnum {
    A,
    B,
    C,
}
  • Используйте расширение Iterator::copied на итераторе. Это копирует каждое значение, делая так, чтобы итератор выдавал T вместо &T. Обратите внимание, что в настоящее время это ночной API, поэтому вам придется подождать немного дольше, чтобы он стал стабильным.
#[derive(Copy)]
enum SomeEnum {
    A,
    B,
    C,
}
let values = vec![SomeEnum::A, SomeEnum::B];

for val in values.iter().copied() {
    let i = val as i32;
}
  • Сделать это клоном. Clone - это признак, который позволяет разработчику impl копировать данные, а также выполнять другую операцию с ним, в случае, если просто Copy битовое использование небезопасно.
#[derive(Clone)]
enum SomeEnum {
    A,
    B,
    C,
}
  • Используйте Iterator::cloned. Это, опять же, идея, аналогичная Iterator::copied, за исключением того, что Clone s объекты и стабильны
#[derive(Clone)]
enum SomeEnum {
    A,
    B,
    C,
}
let values = vec![SomeEnum::A, SomeEnum::B];

for val in values.iter().cloned() {
    let i = val as i32;
}
  • Потребление Vec. Это делает так, что вы больше не можете использовать Vec, и вместо этого каждое из значений используется в Vec. Это наименее гибкий подход, из-за которого вы теряете доступ к values, поскольку он перемещен в into_iter(self).
enum SomeEnum {
    A,
    B,
    C,
}
let values = vec![SomeEnum::A, SomeEnum::B];

for val in values.into_iter() {
    let i = val as i32;
}

Есть несколько других способов решения этой проблемы, но они самые простые.

Другие способы сделать это:

  • Пользовательские impl математических операций
  • Реализуйте черту From, чтобы сделать ее более очевидной при конвертации.
2 голосов
/ 28 мая 2019

iter перебирает коллекцию, используя ссылки на элементы. into_iter, который вызывает движение, даст вам доступ к фактическим элементам. Если с ходом все в порядке, это может помочь упростить приведение порядковых значений перечислений:

for val in values.into_iter() {
    let i = val as i32;
    // if i < X do something
}

В качестве альтернативы, если вы хотите иметь возможность повторять вектор снова, вы можете использовать клон:

#[derive(Clone)]
enum SomeEnum {
    A,
    B,
    C,
}

Позволяет разыграть после выделения нового экземпляра значения перечисления:

let values = vec![SomeEnum::A, SomeEnum::B];
for val in values.iter() {
    let i = (val.clone()) as i32;
    // if i < X do something
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...