Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

delete() und Array

0 views
Skip to first unread message

Helmut Schneider

unread,
Nov 9, 2009, 10:46:58 AM11/9/09
to
Hi,

ein delete() auf Elemente eines Array angewendet l�scht ja den
angegebenen Index, ohne die restlichen Indices anzulangen. Muss man nun
das alte Array Index f�r Index in ein neues kopieren, um die L�cken zu
schliessen, oder gibt es daf�r eine Funktion?

Danke und Gru�, Helmut

--
No Swen today, my love has gone away
My mailbox stands for lorn, a symbol of the dawn

Tobias Nissen

unread,
Nov 9, 2009, 10:52:55 AM11/9/09
to
Helmut Schneider wrote:
> ein delete() auf Elemente eines Array angewendet löscht ja den

> angegebenen Index, ohne die restlichen Indices anzulangen. Muss man
> nun das alte Array Index für Index in ein neues kopieren, um die
> Lücken zu schliessen, oder gibt es dafür eine Funktion?

Ja! perldoc -f splice

Wolf Behrenhoff

unread,
Nov 9, 2009, 12:09:08 PM11/9/09
to
Helmut Schneider wrote:
> Hi,
>
> ein delete() auf Elemente eines Array angewendet l�scht ja den
> angegebenen Index, ohne die restlichen Indices anzulangen. Muss man nun
> das alte Array Index f�r Index in ein neues kopieren, um die L�cken zu
> schliessen, oder gibt es daf�r eine Funktion?

perldoc -f delete

Das verweist dich auch auf splice, wie Tobias schon geschrieben hat. Ich
m�chte eigentlich nur noch hinzuf�gen, dass ich pers�nlich splice
�u�erst selten ben�tige - es ist ja auch keine billige Operation.

Dabei f�llt mir gerade noch auf, dass perldoc -f splice im Beispiel
folgenden Code enth�lt:

sub aeq { ... }
if (&aeq(...)) { ... }

Also die Funktion unn�tigerweise mit & aufgerufen wird. Wo/wem kann ich
vorschlagen, dass das & entfernt wird?

Wolf

Helmut Schneider

unread,
Nov 10, 2009, 5:53:28 AM11/10/09
to
Tobias Nissen wrote:

Verhält sich splice "unerwartet", oder ich mich?

use Data::Dumper;

my @array = qw(A B C BD E BE F G B);
my $index = 0;

print "Array before:\n" . Dumper(@array) . "\n";
foreach my $entry (@array) {
print "Current \$entry: $entry\n";
unless ($entry =~ m/B/i) {
print "Removing \$array[$index]: $array[$index]\n";
splice(@array, $index, 1);
} else {
print "Increasing \$index: $index\n";
$index++;
}
}
print "\nArray after:\n" . Dumper(@array) . "\n";

# perl ./test.pl
Array before:
$VAR1 = 'A';
$VAR2 = 'B';
$VAR3 = 'C';
$VAR4 = 'BD';
$VAR5 = 'E';
$VAR6 = 'BE';
$VAR7 = 'F';
$VAR8 = 'G';
$VAR9 = 'B';

Current $entry: A
Removing $array[0]: A
Current $entry: C
Removing $array[0]: B
Current $entry: E
Removing $array[0]: C
Current $entry: F
Removing $array[0]: BD
Current $entry: B
Increasing $index: 0

Array after:
$VAR1 = 'E';
$VAR2 = 'BE';
$VAR3 = 'F';
$VAR4 = 'G';
$VAR5 = 'B';

#

Wolf Behrenhoff

unread,
Nov 10, 2009, 7:58:52 AM11/10/09
to
Helmut Schneider wrote:
> Tobias Nissen wrote:
>
>> Helmut Schneider wrote:
>>> ein delete() auf Elemente eines Array angewendet löscht ja den
>>> angegebenen Index, ohne die restlichen Indices anzulangen. Muss man
>>> nun das alte Array Index für Index in ein neues kopieren, um die
>>> Lücken zu schliessen, oder gibt es dafür eine Funktion?
>> Ja! perldoc -f splice
>
> Verhält sich splice "unerwartet", oder ich mich?

Du dich.

Denn dein Fehler ist, dass du mit for (@array) loopst und innerhalb der
Loop dann Splice auf das Array verwendest, über das du loopst. Perldoc
schreibt dazu:

Zitat aus perldoc perlsyn:
If any part of LIST is an array, "foreach" will get very confused if you
add or remove elements within the loop body, for example with "splice".
So don't do that.
Zitat Ende

Für das, was du machen möchtest, eignet sich grep aber sowieso viel
besser als splice. Dann ist dein komplettes Programm ein Befehl.

Wolf

Tobias Nissen

unread,
Nov 10, 2009, 8:07:34 AM11/10/09
to
Helmut Schneider wrote:
> Tobias Nissen wrote:
>> Helmut Schneider wrote:
>>> ein delete() auf Elemente eines Array angewendet löscht ja den
>>> angegebenen Index, ohne die restlichen Indices anzulangen. Muss
>>> man nun das alte Array Index für Index in ein neues kopieren, um
>>> die Lücken zu schliessen, oder gibt es dafür eine Funktion?
>>
>> Ja! perldoc -f splice
>
> Verhält sich splice "unerwartet", oder ich mich?

Du Dich. :-)

Hier stimmt's noch.

> Current $entry: C
> Removing $array[0]: B

Hier nicht mehr. foreach ist mit seinem internen Zähler schon einen
Schritt weiter, index nicht (weil index ja erst gesetzt wird, wenn
vorher kein Element entfernt wurde). Am einfachsten ist es wohl, wenn
Du kein foreach benutzt:

diff --git a b
index e019352..6499773 100644
--- a
+++ b
@@ -4,9 +4,10 @@ my @array = qw(A B C BD E BE F G B);


my $index = 0;

print "Array before:\n" . Dumper(@array) . "\n";

-foreach my $entry (@array) {
- print "Current \$entry: $entry\n";
- unless ($entry =~ m/B/i) {
+my $array_size = scalar @array;
+for (my $i = 0; $i < $array_size; $i++) {
+ print "Current entry: $array[$index]\n";
+ unless ($array[$index] =~ m/B/i) {


print "Removing \$array[$index]: $array[$index]\n";
splice(@array, $index, 1);
} else {

Einen schönen Bug gäbe es hier, wenn man nicht auf < $array_size prüfen
würde, sondern "direkt" auf < scalar(@array).

Wolf Behrenhoff

unread,
Nov 10, 2009, 8:27:16 AM11/10/09
to
Tobias Nissen wrote:
> Hier nicht mehr. foreach ist mit seinem internen Zähler schon einen
> Schritt weiter, index nicht (weil index ja erst gesetzt wird, wenn
> vorher kein Element entfernt wurde). Am einfachsten ist es wohl, wenn
> Du kein foreach benutzt:
>
> diff --git a b
> index e019352..6499773 100644
> --- a
> +++ b
> @@ -4,9 +4,10 @@ my @array = qw(A B C BD E BE F G B);
> my $index = 0;
>
> print "Array before:\n" . Dumper(@array) . "\n";
> -foreach my $entry (@array) {
> - print "Current \$entry: $entry\n";
> - unless ($entry =~ m/B/i) {
> +my $array_size = scalar @array;
> +for (my $i = 0; $i < $array_size; $i++) {
> + print "Current entry: $array[$index]\n";
> + unless ($array[$index] =~ m/B/i) {
> print "Removing \$array[$index]: $array[$index]\n";
> splice(@array, $index, 1);
> } else {
>
> Einen schönen Bug gäbe es hier, wenn man nicht auf < $array_size prüfen
> würde, sondern "direkt" auf < scalar(@array).

Das ist doch alles Murx so, mit Verlaub! Allein schon, weil du 2 Indizes
hast, $i und $index. Da blickt man doch nicht richtig durch!

Das kannst du leichter und nur mit einem Index machen, wenn du von
hinten anfängst die Elemente herauszuschmeißen. Aber auch dann ist das
immer noch schlechtes Perl.

Wie wäre es mit:

@array = grep /B/i, @array;

Das ist doch gleich viel lesbarer?!

- Wolf

Tobias Nissen

unread,
Nov 10, 2009, 8:46:27 AM11/10/09
to
Wolf Behrenhoff wrote:
> Tobias Nissen wrote:
[...]

> Das ist doch alles Murx so, mit Verlaub! Allein schon, weil du 2
> Indizes hast, $i und $index. Da blickt man doch nicht richtig durch!

Natürlich ist das Murks. Ich kann aber nicht ahnen, was zwischen den
Zeilen bei Helmut eventuell noch passiert, das haben Minimalbeispiele so
an sich.

> Das kannst du leichter und nur mit einem Index machen, wenn du von
> hinten anfängst die Elemente herauszuschmeißen. Aber auch dann ist
> das immer noch schlechtes Perl.

Ich wollte seine Struktur beibehalten, damit er den Fehler sieht. Und
es gab ja nicht nur meine eine Antwort, sondern auch noch Deine. Da
kann man sich dann prima alle nötigen Informationen raussuchen.

Das Problem bei zu viel Abstraktion ist nunmal, dass man Fehler die im
Detail stecken nicht mehr findet.

> Wie wäre es mit:
>
> @array = grep /B/i, @array;
>
> Das ist doch gleich viel lesbarer?!

Ja. Und wahrscheinlich reicht's ihm auch.

Helmut Schneider

unread,
Nov 10, 2009, 8:51:59 AM11/10/09
to
Wolf Behrenhoff wrote:

> Wie wäre es mit:
>
> @array = grep /B/i, @array;

Herje, so einfach...

Merci.

Peter J. Holzer

unread,
Nov 10, 2009, 11:33:07 AM11/10/09
to
On 2009-11-09 17:09, Wolf Behrenhoff <nospampleaseb...@gmx.net> wrote:
> Dabei f�llt mir gerade noch auf, dass perldoc -f splice im Beispiel
> folgenden Code enth�lt:
>
> sub aeq { ... }
> if (&aeq(...)) { ... }
>
> Also die Funktion unn�tigerweise mit & aufgerufen wird. Wo/wem kann ich
> vorschlagen, dass das & entfernt wird?

Die p5p Mailingliste oder http://rt.perl.org/perlbug/

hp

0 new messages