Font
[thread]8272[/thread]

Anonyme Arrays miteinander vergleichen.

Readers: 3


<< >> 9 entries, 1 page
toby
 2006-08-28 02:29
#69263 #69263
User since
2006-04-14
66 articles
BenutzerIn
[default_avatar]
Hallo Forum! :)

ich habe wieder mal ein Problem, bei dem ich ohne Eure hilfe nicht weiterkomme :(

Gegeben ist auf der einen Seite ein Master-Array, welches als Elemente Hashes enthält, die wiederum Arrays als Values der Keys haben. Auf der anderen Seite haben wir mehrere autonome Hashes, welche Arrays als Values haben. Die Aufgabe ist es zu prüfen, ob und welcher dieser autonomen Hashes als Hash im Master-Array vorhanden ist... hört sich kompliziert an, ist aber nicht.. schaut bitte mein bisheriges Code:

Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#!/usr/bin/perl

use strict;
use warnings;

# Master-Array
my $master = [
{ x => ['1','a'], y => [], z => ['4'], },
{ x => ['b','a'], y => ['1','a'], z => ['1'], },
{ x => ['1','a'], y => [], z => [1], },
{ x => [], y => ['a','1'], z => ['2'], },
];

# autonome Hashes
my $h1 = { x => ['1','a'] , y => [] , z => ['4'] };
my $h2 = { x => ['a'] , y => [] , z => ['1'] };
my $h3 = { x => ['1'] , y => ['a',1] , z => [2] };
my $h4 = { x => [] , y => ['a1'] , z => ['1','2'] };

my @checkit = ($h1,$h2);
my $hrefCount;

foreach my $href (@checkit){
$hrefCount++;
masterElemente($href);
printf "ende von hrefCount: %s\n",$hrefCount;
};


sub masterElemente{
my $href = shift;
for my $element (0..$#{$master}){
printf "MASTERELEMENT: %s\n",$element;
my $count=0;
my $masterKeys = keys (%{@{$master}[$element]});
foreach my $key (keys %$href){
printf "key: $key\n";
printf "\tmaster:\t@{$master->[$element]->{$key}}\n";
printf "\thref:\t@{$href->{$key}}\n";

next if ( ($href->{$key}) != ($master->[$element]->{$key}) );

printf "count=%s\n",$count;
$count++;
}
printf "\n";
printf "BINGO beim $element element (gezaehlt von 0-$#{$master})!\n" if $masterKeys eq $count;
printf "\n";
last if $masterKeys eq $count;
}
}


Alles bis auf den eigentlichen Vergleich (die Zeile mit "next if" ) funktioniert schon ganz gut, nur den eigentlichen Vergleich bekomme ich nicht hin.. Muss ich dort durch die anonymen Arrays noch durchiterieren? Wie mache ich das hier in diesem Falle? Vor lauter Bäumen sehe ich den Wald nicht mehr und hab keine Idee mehr :(

Kann mir bitte jemand helfen?
Danke ! :)
Tobias\n\n

<!--EDIT|toby|1156717917-->
esskar
 2006-08-28 09:13
#69264 #69264
User since
2003-08-04
7321 articles
ModeratorIn

user image
ja, du musst wirklich die elemente der Arrays einzeln vergleichen. CPAN:Array::Compare wird dir dabei helfen.
topeg
 2006-08-28 09:54
#69265 #69265
User since
2006-07-10
2611 articles
BenutzerIn

user image
in deinem fall würde ich auf "Data::Dumper" zurückgreifen, da die gesammte Struktur verglichen werden soll.
Hier meine Variante:
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#!/usr/bin/perl

use strict;
use warnings;
use Data::Dumper;
$Data::Dumper::Indent=0;

# Master-Array
my $master = [
{ x => ['1','a'], y => [], z => ['4'], },
{ x => ['b','a'], y => ['1','a'], z => ['1'], },
{ x => ['1','a'], y => [], z => [1], },
{ x => [], y => ['a','1'], z => ['2'], },
];

# autonome Hashes
my $h1 = { x => ['1','a'] , y => [] , z => ['4'] };
my $h2 = { x => ['a'] , y => [] , z => ['1'] };
my $h3 = { x => ['1'] , y => ['a',1] , z => [2] };
my $h4 = { x => [] , y => ['a1'] , z => ['1','2'] };

my @checkit = ($h1,$h2,$h3,$h4);
my $hrefCount;

foreach my $href (@checkit){
$hrefCount++;
masterElemente($href);
printf "ende von hrefCount: %s\n",$hrefCount;
};

sub masterElemente
{
my $href = shift;
my $skey_suche=Dumper($href);
for my $pos (0..$#{$master})
{
my $skey_master=Dumper($$master[$pos]);
if($skey_master eq $skey_suche)
{
print "BINGO im Element an der Position $pos (".@{$master}." Elemente)!\n";
last;
}
}
}
esskar
 2006-08-28 13:05
#69266 #69266
User since
2003-08-04
7321 articles
ModeratorIn

user image
kann man sich drauf verlassen, dass bei 2 hashes mit gleichen keys, die keys auch wirklich in der gleichen reihenfolge angelegt sind?
pq
 2006-08-28 13:59
#69267 #69267
User since
2003-08-04
12204 articles
Admin1
[Homepage]
user image
denke nicht. zumindest ist das nirgends dokumentiert.
du kannst dich nur drauf verlassen, dass bei zwei dumps
desselben hashes hintereinander dieselbe reihenfolge rauskommt
(wenn du in der zwischzeit nichts neues eingefügt hast)
Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live. -- Damian Conway in "Perl Best Practices"
lesen: Wiki:Wie frage ich & perlintro Wiki:brian's Leitfaden für jedes Perl-Problem
topeg
 2006-08-28 20:52
#69268 #69268
User since
2006-07-10
2611 articles
BenutzerIn

user image
Darüber habe ich mir noch nie Gedanken gemacht...
Bisher hatte ich mit solchen vergleichen keine Probleme. Aber stimmt schon verlassen kann man sich nicht umbedingt darauf.

EDIT:
Aber das behebt das mögliche Problem:
Code: (dl )
$Data::Dumper::Sortkeys=1;
\n\n

<!--EDIT|topeg|1156784383-->
Ronnie
 2006-08-28 21:23
#69269 #69269
User since
2003-08-14
2022 articles
BenutzerIn
[default_avatar]
Ich würde eine etwas andere Vorgehensweise empfehlen. Hier mein Ansatz:
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#!/usr/bin/perl

use strict;
use warnings;

package State;
use Moose;

has 'x' => ( is => 'rw', isa => 'ArrayRef' );
has 'y' => ( is => 'rw', isa => 'ArrayRef' );
has 'z' => ( is => 'rw', isa => 'ArrayRef' );

sub compare {
my $self = shift;
my $other = shift;

my $is_equal = 1;
for (sort keys %$self) {
$is_equal = 0 unless _arr_eq( $self->{$_}, $other->{$_} )
}

return $is_equal;
}

sub _arr_eq {
my $arr1 = shift;
my $arr2 = shift;
return '0' if $#$arr1 != $#$arr2;

my $is_equal = 1;
for (0 .. $#$arr1) {
$is_equal = 0 unless ($arr1->[$_] eq $arr2->[$_]);
}
return $is_equal;
}

package main;
use Data::Dumper;

my $master = new State ( x => ['1','a'], y => [], z => ['4'], );
my $h1 = new State ( x => ['1','a'], y => [], z => ['4'] );
my $h2 = new State ( x => ['a'], y => [], z => ['1'] );

print "\$h1 is identical.\n" if $master->compare($h1);
print "\$h2 is identical.\n" if $master->compare($h2);
Crian
 2006-08-29 14:57
#69270 #69270
User since
2003-08-04
5856 articles
ModeratorIn
[Homepage]
user image
Spannender Ansatz =)
Eventuell könnte man die Sache noch beschleunigen, indem man die beiden for-Schleifen im Fehlerfall mit last verlässt.
s--Pevna-;s.([a-z]).chr((ord($1)-84)%26+97).gee; s^([A-Z])^chr((ord($1)-52)%26+65)^gee;print;

use strict; use warnings; Link zu meiner Perlseite
Ronnie
 2006-08-29 20:27
#69271 #69271
User since
2003-08-14
2022 articles
BenutzerIn
[default_avatar]
@Crian: Danke, man kann das Ganze sogar noch etwas netter machen wenn man CPAN:overload verwendet:
Code: (dl )
1
2
3
4
5
6
7
8
# ...
package State;
use Moose;
use overload '==' => \&compare;

# ...
print "\$h1 is identical.\n" if $master == $h1;
print "\$h2 is identical.\n" if $master == $h2;
\n\n

<!--EDIT|Ronnie|1156868933-->
<< >> 9 entries, 1 page



View all threads created 2006-08-28 02:29.