简体   繁体   English

如何修改列表中的结构条目?

[英]How to modify a struct entry in a list?

I'm struggling to understand how to modify a struct entry in a list by invoking a function.我正在努力理解如何通过调用函数来修改列表中的struct条目。 In the write_largest_to_first function, I would like to set the first entry in a job list with the largest value of age.write_largest_to_first函数中,我想设置具有最大年龄值的作业列表中的第一个条目。 (I don't care about the remaining entries at the moment.) (我现在不关心剩余的条目。)

#![allow(unused)]
struct Job {
    age: i8
}

// Version 1
fn write_largest_to_first(list: &mut [Job]) -> &Job {
    let mut largest = &mut list[0];

    for item in list[1..].iter_mut() {
        if item.age > largest.age {
            largest.age = item.age;
        }
    }
    largest
}

fn main() {
    let mut job_list = vec![
        Job{age: 10},
        Job{age: 3},
        Job{age: 120}];

    println!("Before write_largest_to_first, the first job has age {}", job_list[0].age);
    let result = write_largest_to_first(&mut job_list);
    println!("The oldest job has age {}", result.age);
    
    let first_job = &job_list[0];
    println!("After write_largest_to_first, the first job has age {}", first_job.age);
}

However, the code cannot be compiled:但是,无法编译代码:

error[E0499]: cannot borrow `*list` as mutable more than once at a time
  --> src/main.rs:9:17
   |
6  | fn write_largest_to_first(list: &mut [Job]) -> &Job {
   |                                 - let's call the lifetime of this reference `'1`
7  |     let mut largest = &mut list[0];
   |                       ------------ first mutable borrow occurs here
8  | 
9  |     for item in list[1..].iter_mut() {
   |                 ^^^^ second mutable borrow occurs here
...
14 |     largest
   |     ------- returning this value requires that `list[_]` is borrowed for `'1`

error: aborting due to previous error

Questions:问题:

  1. Refer to another post , modifying the elements that you get from the iterator is allowed.参考另一篇文章,允许修改从迭代器获取的元素。 I have tried to skip the first entry using slice, why doesn't it work?我试图使用切片跳过第一个条目,为什么它不起作用?
  2. Ultimately, I would like to replace largest.age = item.age;最终,我想替换largest.age = item.age; by largest = item;largest = item; . . What is the proper way to achieve this?实现这一目标的正确方法是什么?

Regarding your first question, your main problem is that you create two concurrent mutable borrows of the list.关于您的第一个问题,您的主要问题是您创建了列表的两个并发可变借用。 The borrow checker cannot see that these borrows do not actually overlap.借用检查器无法看到这些借用实际上并未重叠。 The easiest solution is to use the split_first_mut() method to split the first element off the slice in a way that you retain mutable access to the remainder:最简单的解决方案是使用split_first_mut()方法以保留对剩余部分的可变访问的方式将第一个元素从切片中分离出来:

fn write_largest_to_first(list: &mut [Job]) -> &Job {
    let (largest, tail) = list.split_first_mut().unwrap();
    for item in tail.iter_mut() {
        if item.age > largest.age {
            largest.age = item.age;
        }
    }
    largest
}

Regarding your second question, the easiest option is to track the index of the element with the largest age.关于你的第二个问题,最简单的选择是跟踪年龄最大的元素的索引。 Once you found the right index, you can copy the element to the beginning of the list.找到正确的索引后,您可以将元素复制到列表的开头。 This of course requires Job to implement Clone , since otherwise we can't create copies.这当然需要Job实现Clone ,否则我们无法创建副本。

#[derive(Clone)]
struct Job {
    age: i8,
}

fn write_largest_to_first(list: &mut [Job]) -> &Job {
    let mut max_age_index = 0;
    for i in 1..list.len() {
        if list[i].age > list[max_age_index].age {
            max_age_index = i;
        }
    }
    list[0] = list[max_age_index].clone();
    &list[0]
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM