title: How can I iterate a vector once and insert/remove/modify multiple elements along the way?
body: <p>I want to iterate an array/vector once and modify multiple elements on the way as this is the most optimal solution. I don't want to scan it again and again just because Rust is unhappy about borrows.</p>
  
  <p>I store a list of intervals represented as <code>[start;stop]</code> in a sorted vector and I want to add a new interval. It might be overlapping, so I want to remove all elements that are not needed anymore. I want to do it all in one go. Algorithm can look something like this (I cut some parts):</p>
  
  <pre><code>use std::cmp::{min, max};
  
  #[derive(Debug, PartialEq, Clone, Copy)]
  struct Interval {
      start: usize,
      stop: usize,
  }
  
  impl Interval {
      fn new(start: usize, stop: usize) -&gt; Interval {
          Interval {
              start: start,
              stop: stop,
          }
      }
      pub fn starts_before_disjoint(&amp;self, other: &amp;Interval) -&gt; bool {
          self.start &lt; other.start &amp;&amp; self.stop &lt; other.start
      }
      pub fn starts_before_non_disjoint(&amp;self, other: &amp;Interval) -&gt; bool {
          self.start &lt;= other.start &amp;&amp; self.stop &gt;= other.start
      }
      pub fn starts_after(&amp;self, other: &amp;Interval) -&gt; bool {
          self.start &gt; other.start
      }
      pub fn starts_after_disjoint(&amp;self, other: &amp;Interval) -&gt; bool {
          self.start &gt; other.stop
      }
      pub fn starts_after_nondisjoint(&amp;self, other: &amp;Interval) -&gt; bool {
          self.start &gt; other.start &amp;&amp; self.start &lt;= other.stop
      }
      pub fn disjoint(&amp;self, other: &amp;Interval) -&gt; bool {
          self.starts_before_disjoint(other)
      }
      pub fn adjacent(&amp;self, other: &amp;Interval) -&gt; bool {
          self.start == other.stop + 1 || self.stop == other.start - 1
      }
      pub fn union(&amp;self, other: &amp;Interval) -&gt; Interval {
          Interval::new(min(self.start, other.start), max(self.stop, other.stop))
      }
      pub fn intersection(&amp;self, other: &amp;Interval) -&gt; Interval {
          Interval::new(max(self.start, other.start), min(self.stop, other.stop))
      }
  }
  
  fn main() {
      //making vectors
      let mut vec = vec![
          Interval::new(1, 1),
          Interval::new(2, 3),
          Interval::new(6, 7),
      ];
      let addition = Interval::new(2, 5); // &lt;- this will take over interval @ 2 and will be adjacent to 3, so we have to merge
      let (mut i, len) = (0, vec.len());
      while i &lt; len {
          let r = &amp;mut vec[i];
          if *r == addition {
              return; //nothing to do, just a duplicate
          }
          if addition.adjacent(r) || !addition.disjoint(r) {
              //if they are next to each other or overlapping
              //lets merge
              let mut bigger = addition.union(r);
              *r = bigger;
              //now lets check what else we can merge
              while i &lt; len - 1 {
                  i += 1;
                  let next = &amp;vec[i + 1];
                  if !bigger.adjacent(next) &amp;&amp; bigger.disjoint(next) {
                      //nothing to merge
                      break;
                  }
                  vec.remove(i); //&lt;- FAIL another mutable borrow
                  i -= 1; //lets go back
                  vec[i] = bigger.union(next); //&lt;- FAIL and yet another borrow
              }
              return;
          }
          if addition.starts_before_disjoint(r) {
              vec.insert(i - 1, addition); // &lt;- FAIL since another refence already borrowed @ let r = &amp;mut vec[i]
          }
          i += 1;
      }
  }
  </code></pre>
  
  <p>It fails in a couple of places because of the borrowing rules. Is there a way to either</p>
  
  <ol>
  <li>do it with iterators in one go</li>
  <li>work around the borrowing</li>
  </ol>
  
  <p>There is <a href="https://doc.rust-lang.org/nomicon/borrow-splitting.html" rel="nofollow noreferrer">borrow splitting</a> available, but I don't see how I can apply it here.</p>