2015-01-23 10 views

Odpowiedz

14

Biorąc kod (w C) dla Array#uniq

rb_ary_uniq(VALUE ary) 
{ 
    VALUE hash, uniq, v; 
    long i; 

    if (RARRAY_LEN(ary) <= 1) 
     return rb_ary_dup(ary); 
    if (rb_block_given_p()) { 
     hash = ary_make_hash_by(ary); 
     uniq = ary_new(rb_obj_class(ary), RHASH_SIZE(hash)); 
     st_foreach(RHASH_TBL(hash), push_value, uniq); 
    } 
    else { 
     hash = ary_make_hash(ary); 
     uniq = ary_new(rb_obj_class(ary), RHASH_SIZE(hash)); 
     for (i=0; i<RARRAY_LEN(ary); i++) { 
      st_data_t vv = (st_data_t)(v = rb_ary_elt(ary, i)); 
      if (st_delete(RHASH_TBL(hash), &vv, 0)) { 
       rb_ary_push(uniq, v); 
      } 
     } 
    } 
    ary_recycle_hash(hash); 

    return uniq; 
} 

w ogólnym przypadku (blok else), tworzy skrót z tablicy (która jednoczy klucz bez zachowania kolejności). Następnie tworzy nową pustą tablicę o odpowiednim rozmiarze. W końcu przechodzi przez pierwszą tablicę i po znalezieniu klucza w haszu kasuje ten klucz i przenosi go do pustej tablicy.

Dlatego zamówienie jest przechowywane.

Powiedziałbym złożoność wynosi O (złożoność (ary_make_hash) + N) w czasie, który jest prawdopodobnie O (N)

+0

Wow, niesamowite odpowiedź! – Antoine

+0

To jest świetne, ponieważ mam potrzebę zachowania kolejności, w której znajduje się pierwsza instancja każdego unikalnego zdarzenia.ie: {1,2,1,4,5,4,6,4} => {1,2 , 4,5,6} Ponieważ ta "cecha" nie jest udokumentowana, czy pozostanie taka sama? – peterk

+0

Kolejność wstawiania haszy jest zachowywana od czasu Rubin 1.9 i wyżej. Zestaw zbudowany jest na haszyszu. Więc to pozostanie niezmienione (zobacz to pytanie SO, aby uzyskać więcej informacji https://stackoverflow.com/questions/773403/ruby-want-a-et-like-object-which-preserves-order#answer-14468621) – astreal

Powiązane problemy