Autor Beitrag
Silvia
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 67



BeitragVerfasst: Mo 14.02.05 09:20 
Ich möchte die Instanzen eines Objekts durchlaufen und die Werte mit einem Regelwerk vergleichen.

Das Regelwerk ist eine Treeview die in etwa so aussieht!

+Land1
++Stadt1
+++Strasse1
++++Name1
+++++schlüssel1
+Land2
++Stadt2
+++Srasse2
++++Name2
+++++schlüssel2
+Land3
++Stadt3
+++Strasse3
++++Name3
+++++schlüssel3

Jetzt möchte ich den Objektwert im Treeview suchen
und den letzten Eintrag des Treeview - Baumes zurückgeben. z.B.:

Werte des Objektes: (Land2;Stadt2;Strasse2)

Jetzt soll die Routine sich den ersten Wert des Objektes mit dem ersten Eintrag des Treeview vergleichen und wenn eine Übereinstimmung gefunden wurde dann nächstes Childnode und nächsten Eintrag aus dem Objekt vergleichen.

Ziel ist es den letzten Eintrag also schlüssel2 herauszubekommen anhand der Werte des Objektes.

Habe diesbezüglich keine Idee und bitte um denkanstöße!
Wie ist sowas am einfachsten zu beweltigen?
MitschL
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 211

Win 98 SE, Win 2000
D5 Pers, D6 Pers und D7 Pro
BeitragVerfasst: Mo 14.02.05 09:35 
Moin,

am einfachsten ist dies rekursiv zu bewerkstelligen. In einer Methode, die als Parameter einen Knoten (der auf einen Wert, wie Land1 sozusagen zeigt) mitbringt, schaust du durch alle untergeordneten Knoten, bis du wieder einen Treffer landest. Diesen benutzt du für einen Selbstaufruf - etwa so:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
function searchNodeByText( node: String ): String;
  //...
begin
  //Hier kann eine Bedingung in einer Schleife rumlungern
  Result := Result + searchNodeByText( newNodeText );
  //...
end;
, bis du schlußendlich am Endknoten (bsp. Endwert Strasse2) landest.
Die Ergebnisse jedes Aufrufes solltest du direkt zurückgeben, um nicht noch eine Schleife danach zu brauchen.

gegrüßt!

_________________
"Bloßes Ignorieren ist noch keine Toleranz." (Theodor Fontane)
Silvia Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 67



BeitragVerfasst: Mo 14.02.05 09:49 
Danke für die schnelle Antwort!

Kannste deine Function noch weiter ausbauen?

Bin delphi - Neuling!
wwwdirk
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 38


D6 Prof / D2005 Prof
BeitragVerfasst: Mo 14.02.05 12:01 
Hallo,

der Suchvorgang nach dem Knoten (Land, Stadt, Strasse) kann auch ohne Rekursion programmiert werden.
Dessen letztes Element zu finden, sollte allerdings rekursiv erfolgen:

z.B. (aber noch nicht getestet):

ausblenden volle Höhe Delphi-Quelltext
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:
function TForm1.SearchLastNode (const Value1, Value2, Value3: string): TTreeNode;
var
  i, j  : integer;
  aNode : TTreeNode;

  function GetLastNode (aNode: TTreeNode): TTreeNode;
  begin
    if aNode.HasChildren then
      // falls Unterknoten vorhanden sind, diese ebenfalls berücksichtigen
      result := GetLastNode (aNode.GetLastChild) // oder:  GetLastNode (aNode.Item[aNode.Count-1]);
  end;

begin
  result := nil; aNode := nil; i := 0;

  // Erster Knoten finden, der auf Level 0 liegen kann ...
  while not Assigned (aNode) and (i <= TreeView1.Items.Count-1) do
    if TreeView1.Items.Item[i].Text = Value1 then
      result := TreeView1.Items[i]
    else
      inc (i);

  // Zweiter und Dritter Wert suchen ...
  if Assigned (aNode) then
  begin
    i := 0;
    while not Assigned (result) and (i <= aNode.Count-1) do
      if aNode.Item[i].Text = Value2 then
      begin
        j := 0;
        while not Assigned (result) and (j <= aNode.Item[i].Count-1) do
          if aNode.Item[i].Item[j].Text = Value3 then
            result := aNode.Item[i].Item[j]
          else
            inc (j);
      end
      else
        inc (i);
  end;

  // Letzter Knoten des Knoten (Land, Stadt, Strasse) finden ...
  if Assigned (result) then
    result := GetLastNode (result);
end;


Viele Grüße

Dirk
MitschL
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 211

Win 98 SE, Win 2000
D5 Pers, D6 Pers und D7 Pro
BeitragVerfasst: Mo 14.02.05 12:35 
Also,

ich hab mal hier was reingekrümelt, was theoretisch laufen könnte. Da ich aber nicht weis, wie die Suchdaten vorliegen, gehe ich von einem Array aus, welches diverse Texte enthält. Zurückgegeben wird eine ID, mit der man den Knoten direkt aus dem TreeView ziehen kann.

ausblenden Delphi-Quelltext
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:
procedure SearchTree( 
  Tree: TTreeView; var NodeHandle: HTreeItem; 
  var SearchWords: Array of String 
);
var currentNode: TTreeNode;
begin
  if Length( SearchWords ) <= 1 then
  begin
    currentNode := Tree.GetNode( NodeHandle );
    // aktuelle Ebene im Baum durchlaufen
    while currentNode <> nil do
    begin
      // Text gefunden? dann bei den untergeordneten weiter
      if currentNode.Text = SearchWords[0] then
      begin
        SearchWords := Copy( SearchWords, 1, Length( SearchWords ) );
        if currentNode.HasChilds then
        begin
          NodeHandle := currentNode.GetFirstChild.ItemID;
          // Hier ist der Selbstaufruf!!
          SearchTree( Tree, NodeHandle, SearchWords );
        end;
      end;
      currentNode.GetNext();
    end;
  end;
end;


Falls du bisher noch nicht mit rekursiven Aufrufen zu tun hattest, dann könnte dies etwas schwer vom Verständnis sein. Das Wichtigste ist, daß diese Selbstaufrufe irgendwann enden, damit die Methode wieder nach 'oben' kommt.
Die Methode gibt dir aufgrund einer TextListe eine ID des Knoten, der den Text des letzten Elements (des Arrays oder der zuletzt Gefundene) darstellt. Damit wäre die Methode nicht unbedingt das Beste, weil sie stets ein Ergebnis zurückliefert: Die letzte Übereinstimmung eines Textes aus der Liste mit einem Wert aus dem Baum, auch wenn entweder die Liste oder der Baum oder beide noch weitergehen.

Der Aufruf wäre dann sowas wie:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
 var 
  searchList: Array of String;
  searchedTreeNode: TTreeNode;
  searchedTreeNodeID: HTreeItem;
  //...
begin
  //dies nur, um überhaupt eine gültige Liste haben (falls jemand auf den C&P-Gedanken kommt  :) )
  searchList := VarArrayOf( 'Land1', 'Stadt3', 'Strasse2', 'Name1', 'Schluessel1' );
  searchedTreeNodeID := myTree.Items.GetFirstNode.ItemID;
  SearchTree( myTree, searchedTreeNodeID, searchList );
  // mit der ID kann man sich den Knoten so holen
  searchedTreeNode := myTree.Items.GetNode( searchedTreeNodeID );
  //...
end;


Hoffe, du kannst damit was anfangen. Ansonsten: Fragen fragen.

gegrüßt!

_________________
"Bloßes Ignorieren ist noch keine Toleranz." (Theodor Fontane)
Silvia Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 67



BeitragVerfasst: Di 15.02.05 10:37 
Genial MitschL,

da währe ich nicht so schnell drauf gekommen!

Vielen Vielen Dank, hat super gefunzt!
Werde es die nächsten Tage noch weiter testen!