2015-04-08 19 views
8

Có cách nào để thực hiện một cái gì đó như sau:Giải nén một Đưa iterator thành một tuple

let v = vec![1,2,3]; 
let (a,b) = v.iter().take(2); 

như vậy mà a=1b=2 ở cuối?

Tôi biết tôi chỉ có thể sử dụng vectơ nhưng tôi muốn có các biến được đặt tên.

+0

Một vấn đề là tuple là loại. Vì vậy, tuple với 2 yếu tố là loại khác biệt từ tuple của 3 yếu tố. mất (2) có thể không phải là chức năng tốt nhất ở đây, nhưng bạn có thể sẽ yêu cầu macro đặc biệt trả về loại thích hợp dựa trên số bạn vượt qua. –

+0

Bạn muốn hành vi nào khi vectơ chứa ít hơn hai mục? – Shepmaster

+0

@Shepmaster là một câu hỏi tuyệt vời. Trong ánh sáng đó tôi không thể nghĩ ra một lý do đủ tốt để chức năng này có thể thực hiện được. – anderspitman

Trả lời

8

Điều này có thể không chính xác những gì bạn đã yêu cầu, nhưng tôi cho rằng bạn hiếm khi muốn chuyển đổi một vector lớn tùy ý thành một bộ tuple. Nếu bạn chỉ muốn trích xuất vài yếu tố đầu tiên của một véc tơ thành một tuple, bạn có thể làm như vậy sử dụng kết hợp mẫu:

#![feature(slice_patterns)] 
fn main() { 
    let v = vec![1,2,3]; 
    let (a, b) = match &v[..] { 
     &[first, second, ref _tail..] => (first, second), 
     _ => unreachable!() 
    }; 
    assert_eq!((a, b), (1,2)); 
} 
+0

Tôi thích điều này, nhưng nó sẽ là tốt đẹp để có một cái gì đó ngắn gọn hơn. Tạo một hàm trả về '(v [0] .clone(), v [1] .clone())' dường như cũng hoạt động. Có một lợi thế một cách này hay cách khác? – anderspitman

+1

Ngoài việc nhân bản, một nhược điểm rõ ràng sẽ là 'v [i]' có thể hoảng loạn trừ khi bạn kiểm tra rõ ràng chiều dài của Vec, điều này sẽ làm cho đoạn mã ngắn gọn hơn. Sử dụng kết hợp mẫu, trình biên dịch sẽ kiểm tra xem trận đấu có đầy đủ không và yêu cầu bạn xử lý Vec của bất kỳ độ dài tùy ý nào. Tất nhiên, bạn không nên chỉ sử dụng không thể truy cập được! macro như trên trừ khi chiều dài của Vec được biết trước. – helios35

+2

Kể từ 'rustc 1.12.0', cú pháp mẫu lát vẫn là thử nghiệm. Xem [Vấn đề # 23121] (https://github.com/rust-lang/rust/issues/23121) – Phil

3

Các itertools thùng có phương pháp như tuplesnext_tuple có thể giúp với điều này.

3

Tôi đã viết macro đệ quy xấu xí này, vì tôi muốn tìm hiểu điều gì đó về macro.

macro_rules! tuplet { 
{ ($y:ident $(, $x:ident)*) = $v:expr } => { 
    let ($y,$($x),*) = tuplet!($v ; 1 ; ($($x),*) ; ($v[0])); }; 
{ $v:expr ; $j:expr ; ($y:ident $(, $x:ident)*) ; ($($a:expr),*) } => { 
    tuplet!($v ; $j+1 ; ($($x),*) ; ($($a),*,$v[$j])) }; 
{ $v:expr ; $j:expr ;() ; $accu:expr } => { $accu } 
} 

Tôi mới làm điều này và có thể rất tệ, vì vậy có nhiều khả năng là cách tốt nhất để làm điều đó. Chỉ là một bằng chứng về khái niệm. Nó cho phép bạn viết

v = vec![1,2,3]; 
tuplet!((a,b,c) = v); 

nơi nào đó trong đó định nghĩa macro bạn tìm thấy những phần $v[$j], mà bạn có thể thay thế bởi $v.nth($j) nếu bạn muốn sử dụng nó cho vòng lặp.

Các vấn đề liên quan