@@ -43,6 +43,7 @@ export grow;
43
43
export grow_fn;
44
44
export grow_set;
45
45
export truncate;
46
+ export dedup;
46
47
export map;
47
48
export mapi;
48
49
export map2;
@@ -625,6 +626,41 @@ fn truncate<T>(&v: ~[const T], newlen: uint) {
625
626
}
626
627
}
627
628
629
+ /**
630
+ * Remove consecutive repeated elements from a vector; if the vector is
631
+ * sorted, this removes all duplicates.
632
+ */
633
+ fn dedup < T : Eq > ( & v : ~[ const T ] ) unsafe {
634
+ if v. len ( ) < 1 { return ; }
635
+ let mut last_written = 0 , next_to_read = 1 ;
636
+ do as_const_buf ( v) |p, ln| {
637
+ // We have a mutable reference to v, so we can make arbitrary changes.
638
+ // (cf. push and pop)
639
+ let p = p as * mut T ;
640
+ // last_written < next_to_read <= ln
641
+ while next_to_read < ln {
642
+ // last_written < next_to_read < ln
643
+ if * ptr:: mut_offset ( p, next_to_read) ==
644
+ * ptr:: mut_offset ( p, last_written) {
645
+ let _dropped <- * ptr:: mut_offset ( p , next_to_read ) ;
646
+ } else {
647
+ last_written += 1 ;
648
+ // last_written <= next_to_read < ln
649
+ if next_to_read != last_written {
650
+ * ptr:: mut_offset ( p, last_written) <-
651
+ * ptr:: mut_offset ( p, next_to_read) ;
652
+ }
653
+ }
654
+ // last_written <= next_to_read < ln
655
+ next_to_read += 1 ;
656
+ // last_written < next_to_read <= ln
657
+ }
658
+ }
659
+ // last_written < next_to_read == ln
660
+ unsafe:: set_len ( v, last_written + 1 ) ;
661
+ }
662
+
663
+
628
664
// Appending
629
665
#[ inline( always) ]
630
666
pure fn append < T : Copy > ( +lhs : ~[ T ] , rhs : & [ const T ] ) -> ~[ T ] {
@@ -2218,6 +2254,51 @@ mod tests {
2218
2254
// If the unsafe block didn't drop things properly, we blow up here.
2219
2255
}
2220
2256
2257
+ #[ test]
2258
+ fn test_dedup( ) {
2259
+ fn case( -a: ~[ uint] , -b: ~[ uint] ) {
2260
+ let mut v = a;
2261
+ dedup( v) ;
2262
+ assert( v == b) ;
2263
+ }
2264
+ case( ~[ ] , ~[ ] ) ;
2265
+ case( ~[ 1 ] , ~[ 1 ] ) ;
2266
+ case( ~[ 1 , 1 ] , ~[ 1 ] ) ;
2267
+ case( ~[ 1 , 2 , 3 ] , ~[ 1 , 2 , 3 ] ) ;
2268
+ case( ~[ 1 , 1 , 2 , 3 ] , ~[ 1 , 2 , 3 ] ) ;
2269
+ case( ~[ 1 , 2 , 2 , 3 ] , ~[ 1 , 2 , 3 ] ) ;
2270
+ case( ~[ 1 , 2 , 3 , 3 ] , ~[ 1 , 2 , 3 ] ) ;
2271
+ case( ~[ 1 , 1 , 2 , 2 , 2 , 3 , 3 ] , ~[ 1 , 2 , 3 ] ) ;
2272
+ }
2273
+
2274
+ #[ test]
2275
+ fn test_dedup_unique( ) {
2276
+ let mut v0 = ~[ ~1 , ~1 , ~2 , ~3 ] ;
2277
+ dedup( v0) ;
2278
+ let mut v1 = ~[ ~1 , ~2 , ~2 , ~3 ] ;
2279
+ dedup( v1) ;
2280
+ let mut v2 = ~[ ~1 , ~2 , ~3 , ~3 ] ;
2281
+ dedup( v2) ;
2282
+ /*
2283
+ * If the ~pointers were leaked or otherwise misused, valgrind and/or
2284
+ * rustrt should raise errors.
2285
+ */
2286
+ }
2287
+
2288
+ #[ test]
2289
+ fn test_dedup_shared( ) {
2290
+ let mut v0 = ~[ @1 , @1 , @2 , @3 ] ;
2291
+ dedup( v0) ;
2292
+ let mut v1 = ~[ @1 , @2 , @2 , @3 ] ;
2293
+ dedup( v1) ;
2294
+ let mut v2 = ~[ @1 , @2 , @3 , @3 ] ;
2295
+ dedup( v2) ;
2296
+ /*
2297
+ * If the @pointers were leaked or otherwise misused, valgrind and/or
2298
+ * rustrt should raise errors.
2299
+ */
2300
+ }
2301
+
2221
2302
#[ test]
2222
2303
fn test_map( ) {
2223
2304
// Test on-stack map.
0 commit comments