I doubt it would have helped very much with respect to those responses
which are bordering(?) on abusive
(You know the ones that go like: “You’re such a dickhead!”, which is
meant by imputation to be understood as “I’m so smart.”, which when
given this exposition of what is really being said, I merely ask “Who
is the dickhead?” Besides, aren’t we supposed to be nice?)
if I had entitled the email slightly more correctly as:
“Why Does Hash Apparently Reorder By Its Internal Representation And
Other Associated Ponderings”
That little “By” is important! As the ensuing discussion illustrates,
the internal representation could be augmented in such a way so as to
allow for it. Gee whiz, even Matz weighed in! Still, there was
nowhere given an explicit statement as to the necessity of hashes
being ordered, and to claim as much would require that what was
written about internal representatons and optimisations (a crap
reference to the hash table) be ignored. Even so, my understanding of
hashes, well, it isn’t very good, not unlike many of my skills;
although I have written a few hashing functions some time ago.
Nevertheless, it would appear as if this is something which has been
brought up before and appears to have sufficient value to be raised
again. I assumed as much. And if it weren’t so, then there wouldn’t
be what I and others appear also to have found to be useful
discussion. Furthermore, not everyone has been on the list since the
Nineties.
And while I do know how to search the mailing list, I went on to ask
about whether it was at all useful to have ordered hashes in spite of
lack of explicit support in Ruby. I wasn’t asking for support for it,
just as to whether I was wanting for something that I might write
myself which might be useful and not ugly, or evil as I put it.
I do want it for something. Even so, after having read the differing
opinions I don’t know whether it should be there in Ruby by default or
not. I think a subclass of OrderedHash would be a good compromise.
(I’m yet take a look at the supplied code. Thanks for that, I will
do…)
What I wanted it for was for honoring the order in which
properties/attributes are attached at runtime to an object. I want to
access properties by both order and key.
To that end I’ve subsequently written almost 200 additional lines of
code to the following which supports the following:
module Enumerable
def all_but_first
d = self.dup
d.first!
d
end
def all_but_last
d = self.dup
d.last!
d
end
def each_but_first
all_but_first.each do |e|
yield e
end
end
def each_but_last
all_but_last.each do |e|
yield e
end
end
end
I liked the idea of having these as methods of Enumerable. Getting
this to work for Array was trivial. Hashes were a nightmare and
occupied about 80-90% of the additional stuff as it would appear to be
consistent with others’ experiences. Here’s a snippet of that almost
200 lines to give you an idea of the complexity of it:
class Array
…
def sort_by_element_invariant(i)
self.sort {|x, y| by_element_invariant(x, y, i)}
end
def by_element_invariant(x, y, i)
if x.is_a?(Array) || y.is_a?(Array) && !(x.is_a?(Hash) ||
y.is_a?(Hash))
by_array_invariant(x, y, i)
elsif x.is_a?(Hash) || y.is_a?(Hash) && !(x.is_a?(Array) ||
y.is_a?(Array))
by_hash_invariant(x, y, i)
elsif (x.is_a?(Array) && y.is_a?(Hash)) || (x.is_a?(Hash) &&
y.is_a?(Array))
by_array_and_hash_invariant(x, y, i)
else
x.to_s <=> y.to_s
end
end
alias_method :sort_by, :sort_by_element_invariant
alias_method :sort_by_element, :sort_by_element_invariant
def by_array_invariant(x, y, i)
if x.is_a?(Array) && is_a?(Array)
x[i].to_s <=> y[i].to_s
elsif x.is_a?(Array)
x[i].to_s <=> y.to_s
else y.is_a?(Array)
x.to_s <=> y[i].to_s
end
end
…
end
The above code was part of what was required to get an aribitrary
array to sort, which was in turn used by the extensions to the Hash
class. Admittedly as much as a half of the code was written for
symmetry and completeness and was not necessarily required for my
immediate needs.
The code however will do the following, which I believe to be
imperfect as to the consistency of its sorting as yet:
a = [[:b, 2], [:c, 4], :a, 45, “d”, [“f”], [2], [:z, 1, 2, 3],
{“s”=>“s”}, {:t=>“t”}, {}, {“v”=>“v”, “u”=>“u”}]
=> [[:b, 2], [:c, 4], :a, 45, “d”, [“f”], [2], [:z, 1, 2, 3],
{“s”=>“s”}, {:t=>“t”}, {}, {“v”=>“v”, “u”=>“u”}]
a.sort_by_element(0)
=> [{}, {“v”=>“v”, “u”=>“u”}, [2], 45, :a, [:b, 2], [:c, 4], “d”,
{:t=>“t”}, [“f”], {“s”=>“s”}, [:z, 1, 2, 3]]
a.to_h
=> {:z=>[1, 2, 3], 0=>{}, 1=>{“v”=>“v”, “u”=>“u”}, 7=>“d”, :b=>2,
2=>[2], 8=>{:t=>“t”}, :c=>4, 3=>45, 9=>[“f”], 4=>:a, 10=>{“s”=>“s”}}
a.to_h.sort_by_key
=> [[0, {}], [1, {“v”=>“v”, “u”=>“u”}], [10, {“s”=>“s”}], [2, [2]],
[3, 45], [4, :a], [7, “d”], [8, {:t=>“t”}], [9, [“f”]], [:b, 2], [:c,
4], [:z, [1, 2, 3]]]
a.as_h
=> {{“s”=>“s”}=>{:t=>“t”}, “d”=>[“f”], [2]=>[:z, 1, 2, 3],
{}=>{“v”=>“v”, “u”=>“u”}, :a=>45, [:b, 2]=>[:c, 4]}
a.as_h.sort_by_key
=> [[{}, {“v”=>“v”, “u”=>“u”}], [[2], [:z, 1, 2, 3]], [:a, 45], [[:b,
2], [:c, 4]], [“d”, [“f”]], [{“s”=>“s”}, {:t=>“t”}]]
Yeah, it needs some tweaking!.. It works fine for all but the most
bizarre sets of objects.
And thanks to the discussion of that 55 lines of code I may implement
something of the sort (pun only intended later) which implements an
array to do ordering support as I go, rather than, or in addition to
subsequent ordering by sorting.
Finally, to those who would take aim, I say "Piss off!’, I’m quite
capable of such of myself with respect to myself. Such attitudes will
have a chiling effect on those who might be able to contribute given
the opportunity and I refuse to cower to arrogance such as yours.
Stupid and annoying people are best ignored. I’m happy to be ignored
until I say something useful. Which means I myself should’ve written
nothing of it, but anyway… Is it a deal?
Meanwhile, “I’m off to grow some hair on my tongue.”, he says in an
unconvincing attempt at a gruff voice…