Учитывая код (в C) для 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;
}
В общем случае (else
блок), он создает хэш из массива (который объединяет ключ без поддержания порядка). Затем он создает новый пустой массив с нужным размером. Наконец, он проходит через первый массив, и когда он находит ключ в хэше, он удаляет этот ключ и выталкивает его в пустой массив.
Следовательно, заказ сохраняется.
Я бы сказал, что сложность O (сложность (ary_make_hash) + N) во времени, что, вероятно, O (N)
Ничего себе, удивительный ответ! – Antoine
Это замечательно, поскольку у меня есть необходимость в сохранении порядка, в котором первый экземпляр каждого уникального события является encuntered.ie: {1,2,1,4,5,4,6,4} => {1,2 , 4,5,6} Поскольку эта «функция» не документирована, она останется прежней? – peterk
Порядок вставки хеша сохраняется с ruby 1.9 и вверх. Набор построен на хеше. Так что это останется неизменным (см. Этот вопрос SO для получения дополнительной информации https://stackoverflow.com/questions/773403/ruby-want-a-set-like-object-which-preserves-order#answer-14468621) – astreal