Toon posts:

[Delphi] Effectiever Array opruimen?

Pagina: 1
Acties:

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Hallo iedereen.

Voor een applicatie die ik tracht te ontwikkelen heb ik een Array waarin een bewerking word opgeslagen. Het is een Array van strings, op de volgende manier opgebouwd:
code:
1
2
3
4
5
array[0] := '23'
array[1] := '+'
array[2] := '3.1415'
array[3] := '*'
array[4] := '35'
enzoverder..
Deze array wordt in het programma zelf weergegeven in een Listbox, waarin men door het selecteren van een element en enkele knoppen de inhoud kan wijzigen. Elke knop beheert het beveiligen van de invoer van de Array door ervoor te zorgen dat enkel de waarden in de array met een even index een numerieke waarde kan bevatten. Door middel van een backspace knop kan men elementen verwijderen, maar op die manier kan er een leeg element in de Array komen te staan, wat niet praktisch is voor de berekening. Ook kan het lastig zijn indien iemand de hele berekening opnieuw moet typen. Hiervoor had ik een functie gemaakt die de array opkuist, dat wil zeggen dat hij alle lege plaatsen verwijderd (dmv indien een lege plek wordt ontdekt, alle elementen achter deze plek een plaats naar links op te schuiven), en nadat de elementen weer mooi op 1 rijtje staan, wordt er nagekeken of er geen 2 numerieke waarden of operatoren naast elkaar staan, indien dit het geval is wordt het tweede van beide vervangen door een lege plaats en wordt het eerste deel terug aangeroepen. Voor al dit heb ik een zeer niet-elegante oplossing geschreven:
Delphi:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
procedure TForm1.realignClick(Sender: TObject);
var
I, u,O,Y: integer;
begin
// Clean up Wrong input
  for Y := 0 to Length(inputArr) - 1 do begin
    for u := 0 to Length(inputArr) - 1 do begin
      if inputArr[u] = '' then begin
        for O := u to Length(inputArr) - 2 do begin
          inputArr[O]:= inputArr[O + 1];
        end;
      end;
      if u <= Length(inputArr) - 2 then begin
        if  ((AnsiContainsText('+-*/', inputArr[u])) and
            (AnsiContainsText('+-*/', inputArr[u+1]))) or
            ((AnsiContainsText('+-*/', inputArr[u]) = False) and
            (AnsiContainsText('+-*/', inputArr[u+1]) = False)) then begin
              inputArr[u+1] := ''
        end;
      end;
    end;
  end;
// End Clean Up.
end;
(Alvast mijn excuses voor slechte uitlijning)

Maar ik kan me bedenken dat dit voor lange berekeningen nogal traag is. Heeft iemand een betere oplossing om te werk te gaan? Een abstract idee is voldoende, het uitschrijven wil ik namelijk graag zelf doen. :+

(Ik hoop dat het duidelijk is)

Alvast bedankt!

Acties:
  • 0 Henk 'm!

  • Reptile209
  • Registratie: Juni 2001
  • Laatst online: 08:13

Reptile209

- gers -

Ik denk dat het met de traagheid nog wel mee zal vallen, tenzij je array 10-duizenden elementen gaat bevatten (en dan nog). Maar ik ben met je eens dat het geen hele nette oplossing is.

Op basis van je huidige structuur kan je het ook efficienter doen: gezien je beveiligde invoer, weet je zeker dat de hele array klopt totdat er een element verwijderd wordt. Het verwijderen van één regel levert dus precies één open plek op, en één 'clash' van twee operators of getallen achter elkaar. Daar hoef je dus niet naar te zoeken, je moet gewoon gaan opschonen vanaf de plaats van de verwijdering totaan het einde van de array. Kleine catch: als de gebruiker meerdere, niet aaneengesloten secties kan verwijderen is het iets lastiger. Echter weet je ook dan precies waar de wijziging zit, dus kan je daar gericht aan het werk.

Als alternatief kan je gaan werken met een linked list (leuk om zelf te programmeren), omdat je dan makkelijker elementen kunt verwijderen. Ieder element heeft een waarde/operator en een pointer naar het volgende (en eventueel het vorige) element. Bij het verwijderen van een element uit de lijst hoef je alleen de 'inkomende' pointer aan het volgende object te hangen en het huidige object vrij te geven. Je houdt dan dus geen lege elementen over.

Succes :).

Zo scherp als een voetbal!


Acties:
  • 0 Henk 'm!

  • farlane
  • Registratie: Maart 2000
  • Laatst online: 23-09 20:04
Zoals Reptile al aangeeft als je vaak elementen verwijdert en toevoegt op willekeurige plaatsen in je container is een linked list geschikter dan een array.

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Maar dan zou ik ongeveer 80% van het programma opnieuw moeten schrijven; wat redelijk veel tijd zou kosten. Bestaat er geen betere manier om dit te doen met Arrays? :)

Acties:
  • 0 Henk 'm!

Verwijderd

Voor het tonen van de gegevens gebruik je al een linked list, nl. de Items property van TListBox, een TStrings afgeleide.
Het lijkt me niet zoveel werk om de boel zodanig om te schrijven dat zo'n lijst voor zowel data als presentatie gebruikt wordt...