Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is a one-line solution to get everything except the last item in a slice without using the last item's index?

Tags:

arrays

slice

rust

In Python, I can do:

a = [1,2,3]
b = a[:-1] #1,2

Rust has syntax to get a slice of a array range where you provide the last index, non-inclusive:

let a = vec![1, 2, 3];
let b = &a[0..2]; // [1, 2]

If I use -1, it causes a compiler error:

let a = vec![1, 2, 3];
let b = &a[0..-1];
error[E0277]: the trait bound `usize: std::ops::Neg` is not satisfied
 --> src/lib.rs:3:19
  |
3 |     let b = &a[0..-1];
  |                   ^^ the trait `std::ops::Neg` is not implemented for `usize`

How can I do this?

example :

i want to transform "x1::x2::x3::...::xn" to "x1::x2::x3::...xn-1"
in python the one line solustion shoud be

case_1 = "a::b::c";
ret = case1.split("::")[:-1]

but what it the one line soluction for rust

let case_1 =  "a::b::c";
let ret = case_1.split("::").collect::<Vec<_>>() //what could i do next?
like image 297
Cong Wu Avatar asked Apr 29 '20 03:04

Cong Wu


2 Answers

I think split_last is what you are looking for: it returns an optional 2-tuple containing a reference to the last element and a slice up to (but excluding) the last element.

I.e. a.split_last().unwrap().1 gets what you request (unwrap assumes that a is non-empty).

If you want to modify the values, there's also its cousin split_last_mut.

like image 125
phimuemue Avatar answered Oct 04 '22 03:10

phimuemue


You can use -1 as long as you add vec.len() in advance:

fn main() {
    let a = vec![1, 2, 3];
    println!("{:?}", &a[0..a.len() - 1]);
}

Because OP asked for a one-liner, you can remove the newline and use non-idiomatic Rust formatting:

fn main() {
    let a = vec![1, 2, 3]; println!("{:?}", &a[0..a.len() - 1]);
}
like image 31
zgerd Avatar answered Oct 04 '22 04:10

zgerd