Rust中自我和集合的易变性问题

Rust中自我和集合的易变性问题,rust,mutability,Rust,Mutability,我正在写一本锈迹斑斑的书,管理着一副纸牌。它具有洗牌、发牌等功能 函数的作用是:获取一个对self的可变引用,该引用允许重新洗牌现有的牌组。这应该非常简单: 从包含一个带有卡片和随机数的元组的数据组中创建一个临时集合 按随机数对集合进行排序 使用临时集合的顺序重建现有层组 这方面的代码如下 pub struct Deck { // A deck contains zero or more cards cards: Vec<Card> } impl Deck { /

我正在写一本锈迹斑斑的书,管理着一副纸牌。它具有洗牌、发牌等功能

函数的作用是:获取一个对self的可变引用,该引用允许重新洗牌现有的牌组。这应该非常简单:

  • 从包含一个带有卡片和随机数的元组的数据组中创建一个临时集合
  • 按随机数对集合进行排序
  • 使用临时集合的顺序重建现有层组
  • 这方面的代码如下

    pub struct Deck {
        // A deck contains zero or more cards
        cards: Vec<Card>
    }
    
    impl Deck {
    
    // shuffle
    pub fn shuffle(&mut self) {
        if self.cards.is_empty() {
            return;
        }
    
        let mut shuffler : Vec<(&Card, u32)> = Vec::with_capacity(self.cards.len());
    
        for card in self.cards.iter() {
            // make a tuple consisting of each card in the input and a random number
            let card_pos = (card, rand::thread_rng().gen::<u32>());
            shuffler.push(card_pos);
        }
    
        // Sort the vector
        shuffler.sort_by_key(|k| k.1);
    
        // Clear the cards
        self.cards.clear();
    
        // Put the cards into the new randomized order
        for card_pos in shuffler {
            let (card, _) = card_pos;
            self.cards.push(*card)
        }
    }
    
    }
    
    这些错误抱怨可变性,我认为这意味着它不喜欢我在范围内或其他地方有多个可变性引用,但我不知道如何修复它。我曾尝试使用大括号分隔符为每个动作生成块,但没有效果。我可能会把它分解成多个函数,但我宁愿它是一个函数。我如何以最少的努力完成这项工作


    注意:我还没有测试排序功能,所以我希望“按键排序”功能符合我的想法,但这只有在我解决了第一个问题后才会起作用。

    shuffler
    属于
    Vec
    类型,即
    卡是一个参考。也就是说,它是指向存储在
    self.cards
    向量下面的缓冲区中的
    Card
    对象的指针。所以
    self.cards.clear()
    会删除
    shuffler
    脚下的内存

    幸运的是,有一个简单的解决方法:不要获取引用并清除向量,将卡移出
    self.cards
    ,使用
    drain

    let mut shuffler: Vec<(Card, u32)> = Vec::with_capacity(self.cards.len());
    for card in self.cards.drain(..) {
        let card_pos = (card, rand::thread_rng().gen::<u32>());
        shuffler.push(card_pos);
    }
    shuffler.sort_by_key(|k| k.1);
    for card_pos in shuffler {
        let (card, _) = card_pos;
        self.cards.push(card);
    }
    
    let mut shuffler:Vec=Vec::with_capacity(self.cards.len());
    对于自卡中的卡。卡。排液(…){
    让card_pos=(card,rand::thread_rng().gen::());
    洗牌器。推(卡片位置);
    }
    shuffler.sort_by_key(| k | k.1);
    用于洗牌器中的卡牌位置{
    let(card,u)=card_pos;
    self.cards.push(卡片);
    }
    

    旁白:有一种就地洗牌算法,它比排序线性时间(而不是O(n logn))更有效,并且常数因子更好

    shuffler
    属于
    Vec
    类型,即
    卡是一个参考。也就是说,它是指向存储在
    self.cards
    向量下面的缓冲区中的
    Card
    对象的指针。所以
    self.cards.clear()
    会删除
    shuffler
    脚下的内存

    幸运的是,有一个简单的解决方法:不要获取引用并清除向量,将卡移出
    self.cards
    ,使用
    drain

    let mut shuffler: Vec<(Card, u32)> = Vec::with_capacity(self.cards.len());
    for card in self.cards.drain(..) {
        let card_pos = (card, rand::thread_rng().gen::<u32>());
        shuffler.push(card_pos);
    }
    shuffler.sort_by_key(|k| k.1);
    for card_pos in shuffler {
        let (card, _) = card_pos;
        self.cards.push(card);
    }
    
    let mut shuffler:Vec=Vec::with_capacity(self.cards.len());
    对于自卡中的卡。卡。排液(…){
    让card_pos=(card,rand::thread_rng().gen::());
    洗牌器。推(卡片位置);
    }
    shuffler.sort_by_key(| k | k.1);
    用于洗牌器中的卡牌位置{
    let(card,u)=card_pos;
    self.cards.push(卡片);
    }
    

    旁白:有一种就地洗牌算法,它比排序线性时间(而不是O(n logn))更有效,并且常数因子更好

    谢谢,成功了。我以前试过,没有使用裁判,我也遇到了其他类似的错误。我会记住洗牌算法,因为我可能会使它尽可能高效。谢谢,这就成功了。我以前试过,没有使用裁判,我也遇到了其他类似的错误。我会记住洗牌算法,因为我可能会尽可能使它高效。