Zeiger eines Arrays zurücksetzen (soll beim nächsten Durchlauf erhalten bleiben);

MissPiggy

Erfahrenes Mitglied
Ein numerisches Array soll durchlaufen werden, sofern ein bestimmter Wert vorkommt sollen Schlüssel und Wert gelöscht werden und der Arrayzeiger um 2 Stellen zurückversetzt werden, so dass er beim nächsten Schleifendurchlauf bei diesen Schlüssel weitermacht. Ist es möglich den Zeiger auf diese Weise zurückzusetzen, ohne Kopien des Arrays zu erzeugen ?



Danke im Vorraus ;)
 
Hier ohne Kopie des Array aber mit Kopien der Einzelwerte:

PHP:
<?php
function removeKeyAndValue(&$array, $value)
{
  $tmp = array();
  $idx = 1;
  foreach($array as $key => $value)
  {
    if($value == 'Bar')
    {
      continue;
    }
    
    $tmp[$idx++] = $value;
  }

  $array = $tmp;  
}

$array = array(
	1 => 'Trash',
    2 => 'Müll',
    3 => 'Foo',
    4 => 'Bar',
    5 => 'Baz'
);

var_dump($array);

removeKeyAndValue($array, 'Bar');

var_dump($array);

Wenn du nur das Element beim Durchlauf raus nimmst (z.B. durch unset), bleiben die ursprünglichen Keys des Arrays erhalten:

PHP:
<?php

$array = array(
	1 => 'Trash',
    2 => 'Müll',
    3 => 'Foo',
    4 => 'Bar',
    5 => 'Baz'
);

var_dump($array);

foreach($array as $key => $value)
{
  if($value == 'Bar')
  {
    unset($array[$key]);
  }
}

var_dump($array);

Jetzt könntest du natürlich etwas kompliziertes machen, wie den Wert des Keys zu merken, den du entfernt hast um am Ende der Schleife das letzte Element zu löschen, aber dann kannst du das Array gleich neu aufbauen, daher auch mein erster Vorschlag.
 
Doppel wegen Korrektur des groben Schnitzers in der removeKeyAndValue()-Funktion:

PHP:
function removeKeyAndValue(&$array, $valueToRemove)
{
  $tmp = array();
  $idx = 1;
  foreach($array as $key => $value)
  {
    if($value == $valueToRemove) // Hier war der Fehler
    {
      continue;
    }
    
    $tmp[$idx++] = $value;
  }
 
  $array = $tmp;  
}
 
Vielen Dank schonmal für die Hilfe

Ich habe alternativ versucht mit der array_splice Funktion bestimmte Elemente zu löschen. Jedoch tritt hier ein Problem auf :

Die Funktion hat einen optionalen 'replacement' Paramenter der den originalen Wert ersetzt, gibt man diesen nicht an wird das betreffende Element gelöscht.
Nun müssten in beiden Fällen dieselben Elemente betroffen sein, im ersten Fall werden alle Elemente die ein 'x' als Wert haben durch ein 'a' ersetzt
PHP:
 if($array[$i]=='x'){
	array_splice($array,$i,1,'a');
	 }

im 2. gelöscht

PHP:
 if($array[$i]=='x'){
	array_splice($array,$i,1);
	 }

Nun tritt folgendes Problem auf - im ersten Fall arbeitet die Funktion wie erwartet, im 2. Fall, wo die Elemente gelöscht werden sollen bleiben einige Elemente erhalten, immer dann wenn im Array mehrere x-Werte hintereinander auftauchen bleibt einer davon erhalten, die restlichen werden (samt Schlüssel) wie gewünscht gelöscht. Dabei ist es unabhängig welche Werte gelöscht werden sollen, es bleiben immer welche erhalten.



Der Inhalt des Arrays stammt aus dieser Sequenz :
Code:
93752xxx746x27x1754xx90x93xxxxx238x44x75xx08750912738x8461x8759383xx328x4x4935903x6x5550360535004x0xx945958961296x267x8842xxx5x6xx61x4x48482x80xxx83316843x7x4x83x9521731xxx25x51xx457x6x5x9698222x771237745034x5133592x27xx8x87xx35221x36x0x50x23x7x63x998418xx

und wird mit
PHP:
$handler=fopen("sequence.txt","r");
$wert=fread($handler, filesize("sequence.txt"));
$array=str_split($wert);
eingelesen.

Wie genau verhält sich die Funktion 'array_splice' an dieser Stelle ?
 
Hmm,

warum löschst du die Werte nicht aus dem String bevor du ihn mittels str_split() aufteilst? Ein simples str_replace("x", "", $wert) dürfte hier doch ausreichend sein? Oder was genau ist der Grund für diese Aktion?

Ansonsten würde ich diesen Satz hier berücksichtigen:

Beachten Sie, dass numerische Schlüssel in input nicht erhalten werden.

Das bedeutet, dass im Falle, du löschst ein Element raus, musst dein Zähler wieder dekrementiert werden:

PHP:
<?php
$wert = "93752xxx746x27x1754xx90x93xxxxx238x44x75xx08750912738x8461x8759383xx328x4x4935903x6x5550360535004x0xx945958961296x267x8842xxx5x6xx61x4x48482x80xxx83316843x7x4x83x9521731xxx25x51xx457x6x5x9698222x771237745034x5133592x27xx8x87xx35221x36x0x50x23x7x63x998418xx";
$array=str_split($wert);

var_dump($array);

for($i = 0; $i < count($array); $i++)
{
  if($array[$i] == 'x')
  {
    array_splice($array, $i--, 1);
  }
}

var_dump($array);
 
Wenn ich das mit einer forSchleife und einem Zähler mache wird bei $i -- der Zähler nicht um eins, sondern um 2 dekrementiert, der Abstand zwischen $i und $i-- beträgt dann 2.
 
Wie hast du die Ausgaben platziert? Bei mir scheint alles zu stimmen:

PHP:
<?php
$wert = "93752xxx746x27x1754xx90x93xxxxx238x44x75xx08750912738x8461x8759383xx328x4x4935903x6x5550360535004x0xx945958961296x267x8842xxx5x6xx61x4x48482x80xxx83316843x7x4x83x9521731xxx25x51xx457x6x5x9698222x771237745034x5133592x27xx8x87xx35221x36x0x50x23x7x63x998418xx";
$array=str_split($wert);

for($i = 0; $i < count($array); $i++)
{
  if($array[$i] == 'x')
  {
    array_splice($array, $i--, 1);
  }
  else
  {
    printf("%d: %d\n", $i, $array[$i]);    
  }
}

Code:
0: 9
1: 3
2: 7
3: 5
4: 2
5: 7
6: 4
7: 6
8: 2
9: 7
10: 1
11: 7
12: 5
13: 4
14: 9
15: 0
16: 9
17: 3
18: 2
19: 3
20: 8
21: 4
22: 4
23: 7
24: 5
25: 0
26: 8
27: 7
28: 5
29: 0
30: 9
31: 1
32: 2
33: 7
34: 3
35: 8
36: 8
37: 4
38: 6
39: 1
40: 8
41: 7
42: 5
43: 9
44: 3
45: 8
46: 3
47: 3
48: 2
49: 8
50: 4
51: 4
52: 9
53: 3
54: 5
55: 9
56: 0
57: 3
58: 6
59: 5
60: 5
61: 5
62: 0
63: 3
64: 6
65: 0
66: 5
67: 3
68: 5
69: 0
70: 0
71: 4
72: 0
73: 9
74: 4
75: 5
76: 9
77: 5
78: 8
79: 9
80: 6
81: 1
82: 2
83: 9
84: 6
85: 2
86: 6
87: 7
88: 8
89: 8
90: 4
91: 2
92: 5
93: 6
94: 6
95: 1
96: 4
97: 4
98: 8
99: 4
100: 8
101: 2
102: 8
103: 0
104: 8
105: 3
106: 3
107: 1
108: 6
109: 8
110: 4
111: 3
112: 7
113: 4
114: 8
115: 3
116: 9
117: 5
118: 2
119: 1
120: 7
121: 3
122: 1
123: 2
124: 5
125: 5
126: 1
127: 4
128: 5
129: 7
130: 6
131: 5
132: 9
133: 6
134: 9
135: 8
136: 2
137: 2
138: 2
139: 7
140: 7
141: 1
142: 2
143: 3
144: 7
145: 7
146: 4
147: 5
148: 0
149: 3
150: 4
151: 5
152: 1
153: 3
154: 3
155: 5
156: 9
157: 2
158: 2
159: 7
160: 8
161: 8
162: 7
163: 3
164: 5
165: 2
166: 2
167: 1
168: 3
169: 6
170: 0
171: 5
172: 0
173: 2
174: 3
175: 7
176: 6
177: 3
178: 9
179: 9
180: 8
181: 4
182: 1
183: 8
 
Zurück