Hi all, I have a method which returns two arrayrefs: one is an array of hashes, and the other an array of arrays. I'm writing a test harness for this method, so I put together some testcases and expected results. I don't care what order the arrays are in; I only care that the arrayrefs returned by the function contains exactly the same set of values as the expected results.
Something like this: # embeddings is an array of hashes, $anchors is an array of arrays my ($embeddings, $anchors) = $embedder->embed($subgraph); my $expected => { embeddings => [ { a => '1', b => '2', }, { a => '1', b => '3', }, { a => '2', b => '3', }, ], anchors => [ ['1','2'], ['2','3'], ['1','3'], ], }, use Test::More tests => 2; is_deeply($embeddings, $expected->{embeddings}, "embeddings match"); is_deeply($anchors, $expected->{anchors}, "anchors match"); ...except that I don't care if the actual and expected array referents are in a different order, only that they contain the same items. My first thought is to sort the arrays according to some arbitrary convention and use is_deeply() as above; but I'm stuck as to how to write a sort ordering well. I'm thinking I should sort the array of hashes by lexicographical ordering of hash values, with lexicographical significance determined by sorted key order, and sort the array of arrays by simple lexicographical order. I have something like this: use List::MoreUtils qw(pairwise); # lexicographical comparison function for lists of hashes sub lexhash { my @seq_a = map {$a->{$_}} sort keys %$a; my @seq_b = map {$b->{$_}} sort keys %$b; for my $pair (pairwise {[$a,$b]} @seq_a, @seq_b) { return $pair->[0] cmp $pair->[1] if $pair->[0] cmp $pair->[1]; } return 0; } # lexicographical comparison function for lists of arrays sub lexarray { for my $pair (pairwise {[$a,$b]} @$a, @$b) { return $pair->[0] cmp $pair->[1] if $pair->[0] cmp $pair->[1]; } return 0; } is_deeply([sort lexhash @$embeddings], [sort lexhash @{$expected->{embeddings}}], "embeddings match"); is_deeply([sort lexarray @$anchors], [sort lexarray @{$expected->{anchors}}], "anchors match"); This works and does what I want, but it feels hacky and I'm not entirely happy about it. I have these questions: 1. Is there a "set" type which holds aggregate data and doesn't care about order, which I could use to compare these results for equality? 2. If not, is my solution to the problem a reasonable design? If not, what better way could I do it? 3. If it's a reasonable design, is there any way my implementation of it could be improved? In particular, could it be made more readable? I'm not convinced that I could work out what this code does next week, let alone in six months time. Phil -- To unsubscribe, e-mail: beginners-unsubscr...@perl.org For additional commands, e-mail: beginners-h...@perl.org http://learn.perl.org/