Oui, Enumerable#group_by
préserve l'ordre de saisie.
est ici la mise en œuvre de cette méthode en IRM, de https://github.com/ruby/ruby/blob/trunk/enum.c: élément
static VALUE
enum_group_by(VALUE obj)
{
VALUE hash;
RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);
hash = rb_hash_new();
rb_block_call(obj, id_each, 0, 0, group_by_i, hash);
OBJ_INFECT(hash, obj);
return hash;
}
static VALUE
group_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, hash))
{
VALUE group;
VALUE values;
ENUM_WANT_SVALUE();
group = rb_yield(i);
values = rb_hash_aref(hash, group);
if (!RB_TYPE_P(values, T_ARRAY)) {
values = rb_ary_new3(1, i);
rb_hash_aset(hash, group, values);
}
else {
rb_ary_push(values, i);
}
return Qnil;
}
enum_group_by
appels group_by_i
sur chaque tableau (obj
) dans l'ordre. group_by_i
crée un tableau à un seul élément (rb_ary_new3(1, i)
) la première fois qu'un groupe est rencontré et appuie sur le tableau par la suite (rb_ary_push(values, i)
). Ainsi, l'ordre d'entrée est préservé.
En outre, RubySpec l'exige. De https://github.com/rubyspec/rubyspec/blob/master/core/enumerable/group_by_spec.rb:
it "returns a hash with values grouped according to the block" do
e = EnumerableSpecs::Numerous.new("foo", "bar", "baz")
h = e.group_by { |word| word[0..0].to_sym }
h.should == { :f => ["foo"], :b => ["bar", "baz"]}
end
'' Enumerable' utilise each' pour parcourir la collection. Changer l'ordre nécessiterait un effort supplémentaire. – Stefan
Mais auparavant, j'ai appris que le 'Enumerable # sort 'reminescent n'est pas stable. Donc, je ne pouvais pas être sûr à ce sujet. – sawa