@@ -137,7 +137,7 @@ pub trait IteratorExt<A>: Iterator<A> {
137
137
///
138
138
/// ```rust
139
139
/// let a = [0i];
140
- /// let b = [1i];
140
+ /// let b = [1i, 2i ];
141
141
/// let mut it = a.iter().zip(b.iter());
142
142
/// let (x0, x1) = (0i, 1i);
143
143
/// assert_eq!(it.next().unwrap(), (&x0, &x1));
@@ -149,6 +149,27 @@ pub trait IteratorExt<A>: Iterator<A> {
149
149
Zip { a : self , b : other}
150
150
}
151
151
152
+ /// Creates an iterator which iterates over both this and the specified
153
+ /// iterators simultaneously, yielding pairs of two optional elements.
154
+ /// When both iterators return None, all further invocations of next() will
155
+ /// return None.
156
+ ///
157
+ /// # Example
158
+ ///
159
+ /// ```rust
160
+ /// let a = [0i];
161
+ /// let b = [1i, 2i];
162
+ /// let mut it = a.iter().zip(b.iter());
163
+ /// let (x0, x1, x2) = (0i, 1i, 2i);
164
+ /// assert_eq!(it.next().unwrap(), (Some(&x0), Some(&x1)));
165
+ /// assert_eq!(it.next().unwrap(), (None, Some(&x2)));
166
+ /// assert!(it.next().is_none());
167
+ /// ```
168
+ #[ inline]
169
+ fn zip_longest < B , U : Iterator < B > > ( self , other : U ) -> ZipLongest < Self , U > {
170
+ ZipLongest { a : self , b : other}
171
+ }
172
+
152
173
/// Creates a new iterator which will apply the specified function to each
153
174
/// element returned by the first, yielding the mapped element instead.
154
175
///
@@ -780,6 +801,9 @@ impl<'a, A, B, T: ExactSizeIterator<A>> ExactSizeIterator<B> for Map<'a, A, B, T
780
801
#[ unstable = "trait is unstable" ]
781
802
impl < A , B , T , U > ExactSizeIterator < ( A , B ) > for Zip < T , U >
782
803
where T : ExactSizeIterator < A > , U : ExactSizeIterator < B > { }
804
+ #[ unstable = "trait is unstable" ]
805
+ impl < A , B , T , U > ExactSizeIterator < ( Option < A > , Option < B > ) > for ZipLongest < T , U >
806
+ where T : ExactSizeIterator < A > , U : ExactSizeIterator < B > { }
783
807
784
808
/// An double-ended iterator with the direction inverted
785
809
#[ deriving( Clone ) ]
@@ -1368,6 +1392,71 @@ RandomAccessIterator<(A, B)> for Zip<T, U> {
1368
1392
}
1369
1393
}
1370
1394
1395
+ /// An iterator which iterates two other iterators simultaneously
1396
+ #[ deriving( Clone ) ]
1397
+ #[ must_use = "iterator adaptors are lazy and do nothing unless consumed" ]
1398
+ pub struct ZipLongest < T , U > {
1399
+ a : T ,
1400
+ b : U
1401
+ }
1402
+
1403
+ impl < A , B , T : Iterator < A > , U : Iterator < B > > Iterator < ( Option < A > , Option < B > ) > for ZipLongest < T , U > {
1404
+ #[ inline]
1405
+ fn next ( & mut self ) -> Option < ( Option < A > , Option < B > ) > {
1406
+ match ( self . a . next ( ) , self . b . next ( ) ) {
1407
+ ( None , None ) => None ,
1408
+ pair_of_options => Some ( pair_of_options) ,
1409
+ }
1410
+ }
1411
+
1412
+ #[ inline]
1413
+ fn size_hint ( & self ) -> ( uint , Option < uint > ) {
1414
+ let ( a_lower, a_upper) = self . a . size_hint ( ) ;
1415
+ let ( b_lower, b_upper) = self . b . size_hint ( ) ;
1416
+
1417
+ let lower = cmp:: max ( a_lower, b_lower) ;
1418
+
1419
+ let upper = match ( a_upper, b_upper) {
1420
+ ( Some ( x) , Some ( y) ) => Some ( cmp:: max ( x, y) ) ,
1421
+ _ => None
1422
+ } ;
1423
+
1424
+ ( lower, upper)
1425
+ }
1426
+ }
1427
+
1428
+ impl < A , B , T : ExactSize < A > , U : ExactSize < B > > DoubleEndedIterator < ( Option < A > , Option < B > ) >
1429
+ for ZipLongest < T , U > {
1430
+ #[ inline]
1431
+ fn next_back ( & mut self ) -> Option < ( Option < A > , Option < B > ) > {
1432
+ use cmp:: { Equal , Greater , Less } ;
1433
+ match self . a . len ( ) . cmp ( & self . b . len ( ) ) {
1434
+ Equal => match ( self . a . next_back ( ) , self . b . next_back ( ) ) {
1435
+ ( None , None ) => None ,
1436
+ pair_of_options => Some ( pair_of_options) ,
1437
+ } ,
1438
+ Greater => self . a . next_back ( ) . map ( |x| ( Some ( x) , None ) ) ,
1439
+ Less => self . b . next_back ( ) . map ( |y| ( None , Some ( y) ) ) ,
1440
+ }
1441
+ }
1442
+ }
1443
+
1444
+ impl < A , B , T : RandomAccessIterator < A > , U : RandomAccessIterator < B > >
1445
+ RandomAccessIterator < ( Option < A > , Option < B > ) > for ZipLongest < T , U > {
1446
+ #[ inline]
1447
+ fn indexable ( & self ) -> uint {
1448
+ cmp:: max ( self . a . indexable ( ) , self . b . indexable ( ) )
1449
+ }
1450
+
1451
+ #[ inline]
1452
+ fn idx ( & mut self , index : uint ) -> Option < ( Option < A > , Option < B > ) > {
1453
+ match ( self . a . idx ( index) , self . b . idx ( index) ) {
1454
+ ( None , None ) => None ,
1455
+ pair_of_options => Some ( pair_of_options) ,
1456
+ }
1457
+ }
1458
+ }
1459
+
1371
1460
/// An iterator which maps the values of `iter` with `f`
1372
1461
#[ must_use = "iterator adaptors are lazy and do nothing unless consumed" ]
1373
1462
#[ stable]
0 commit comments