Objekt array Topic is solved

Stelle Fragen zur Programmierung mit Autohotkey

Moderator: jNizM

pramach
Posts: 49
Joined: 24 Jan 2018, 08:20

Objekt array

06 Apr 2018, 07:27

Hallo
Ich habe ein etwas seltsames, mir nicht erklärliches Verhalten zusammen mit einem Object Array.

Basis ist ein bestehendes Object Array, aus dem ich eine TreeView fülle und das Object Array dabei erweitere ...

Code: Select all

AWS := Object()
AWS.INSERT( "X1",	{ Name: "AAA", Kind: "K1", Collect: "#", Group: "XXX" })
AWS.INSERT( "X2",	{ Name: "BBB", Kind: "K1", Collect: "#", Group: "XXX" })
AWS.INSERT( "X3",	{ Name: "CCC", Kind: "K1", Collect: "#", Group: "" })
AWS.INSERT( "X4",	{ Name: "DDD", Kind: "K2", Collect: "#", Group: "" })
Das Tree das ich erwarte ( und auch bekomme ) ist
K1
...|- #
......|-XXX
.........|- AAA
.........|- BBB
......|-CCC
K2
...|- #
......|-DDD
Einen "Kind" und einen "Collect" Wert habe ich immer, einen "Group" Wert nicht.

Während ich den Tree aufbaue, ersetze ich mein Object Array mit allen Werten im Tree, d.h. insgesamt 9 Object Elemente, die ich jeweils mit einem "Type" (Kind, Collect, Group, Data) ergänze.

Mein Problem nun ist, das im neu generierten Object Array der "Type" bei allen identisch ist ....

Code: Select all

---------------------------
test.ahk
---------------------------
1: Collect=#, Group=XXX, Kind=K1, Name=AAA, Type=DATA		<<< solte eigentlich Type=KIND sein
2: Collect=#, Group=XXX, Kind=K1, Name=AAA, Type=DATA		<<< solte eigentlich Type=COLLECT sein
3: Collect=#, Group=XXX, Kind=K1, Name=AAA, Type=DATA		<<< solte eigentlich Type=GROUP sein
4: Collect=#, Group=XXX, Kind=K1, Name=AAA, Type=DATA		<<< OK
5: Collect=#, Group=XXX, Kind=K1, Name=BBB, Type=DATA		<<< OK
6: Collect=#, Group=, Kind=K1, Name=CCC, Type=DATA		<<< OK
7: Collect=#, Group=, Kind=K2, Name=DDD, Type=DATA		<<< solte eigentlich Type=KIND sein
8: Collect=#, Group=, Kind=K2, Name=DDD, Type=DATA		<<< solte eigentlich Type=COLLECT sein
9: Collect=#, Group=, Kind=K2, Name=DDD, Type=DATA		<<< OK
---------------------------
OK   
---------------------------
Und so kompliziert ist mein Code nun auch nicht

Code: Select all

#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
; #Warn  ; Enable warnings to assist with detecting common errors.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.
#SingleInstance, force

; initialize object array to hold all data
AWS := Object()

; define array content
AWS := Object()
AWS.INSERT( "X1",	{ Name: "AAA", Kind: "K1", Collect: "#", Group: "XXX" })
AWS.INSERT( "X2",	{ Name: "BBB", Kind: "K1", Collect: "#", Group: "XXX" })
AWS.INSERT( "X3",	{ Name: "CCC", Kind: "K1", Collect: "#", Group: "" })
AWS.INSERT( "X4",	{ Name: "DDD", Kind: "K2", Collect: "#", Group: "" })

; create GUI
Gui, -Resize +OwnDialogs +ToolWindow +MinSize

; build the tree
Gui, Add, TreeView, x10 y10 w200 r30 +ReadOnly
GuiControl, -Redraw, treeData
TV_Delete()
AWS2Tree()
GuiControl, +Redraw, treeData

; show GUI
Gui, Show, AutoSize Center, HKHS Setup

; show AWS array content
str := ""
for indexA, itemA in AWS
{
	str .= indexA . ": "
	for indexB,itemB in itemA
		str .= (A_Index > 1 ? ", " : "" ) . indexB . "=" . itemB
	str .= "`n"
}
MsgBox, % str
Return

; close the app
GuiClose:
GuiEscape:
	ExitApp
	
; build the treeview
AWS2Tree()
{
	local key, items, TEMP

	; rebuild item with new key
	TEMP := AWS.Clone()
	AWS := Object()

	; build tree
	for key, items in TEMP
		AWS2TreeItem( items )

	; cleanup
	TEMP := ""
	Return
}

AWS2TreeItem( items )
{
	local pid
	static sKind, sCollect, sGroup	; last used values
	static pKind, pCollect, pGroup	; last used parent ids
	static ID := 0

	; kind change
	if ( items.Kind <> sKind )
	{
		; kind differs, so add as parent for next items
		sKind := items.Kind
		pKind := TV_Add( sKind )				; add on root
				
		items[ "Type" ] := "KIND"
		ID += 1
		AWS[ ID ] := items		; add new object item wit htype KIND

		sCollect := ""			; when kind change also a new collection starts
		sGroup := ""			; when kind change also a new group starts
	}

	; collection changes
	if ( items.Collect <> sCollect )
	{
		; collect differs, so add as parent for next items
		sCollect := items.Collect
		pCollect := TV_Add( sCollect, pKind )	; add as child of KIND
			
		items[ "Type" ] := "COLLECT"
		ID += 1
		AWS[ ID ] := items		; add new object item wit htype KIND
			
		sGroup := ""			; when kind change also a new group starts
	}

	; group change
	if (( StrLen( Trim( items.Group )) > 0 ) && ( items.Group <> sGroup ))
	{
		; group differs, so add as parent for next items
		sGroup := items.Group
		pGroup := TV_Add( sGroup, pCollect )	; add as child of COLLECT
		
		items[ "Type" ] := "GROUP"
		ID += 1
		AWS[ ID ] := items
	}

	; add item
	if ( StrLen( Trim( items.Group )) = 0 )
		pid := TV_Add( items.Name, pCollect )	; no group, add to Collection

	else if ( items.Group = sGroup )
		pid := TV_Add( items.Name, pGroup )		; group exists, add to group

	items[ "Type" ] := "DATA"
	ID += 1
	AWS[ ID ] := items

	; Return
	Return
}
Wo liegt mein Fehler ?

Verwende AHK 1.1.28.00
User avatar
nnnik
Posts: 3527
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: Objekt array

06 Apr 2018, 08:19

Unabhängig von dem was du vorher machst oder was du auch tust wird deine AWS2TreeItem Funktion items.Type auf DATA setzen.
Geh mal deine if/Else struktur durch - du wirst unweigerlich an diesem Punkt ankommen.
Alles was dann vorher Drinnen steht wird endgültig überschrieben - ich glaube du hast da ein paar else vergessen.

Zudem verstehe ich nicht wieso das 2. Element ein Collect sein soll, wenn der Collect wert doch der selbe wie beim ersten ist.
Es wäre besser wenn du erstmal versuchst zu erklären was du eigentlich brauchst und machen willst.
Recommends AHK Studio
just me
Posts: 5642
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Objekt array

06 Apr 2018, 08:20

Moin,

zunächst einmal fügt AWS2TreeItem() dem Array AWS bei jedem Aufruf 2 Elemente hinzu, wenn bei den oberen Prüfungen ein Treffer erzeilt wird, weil die Funktion immer bis zum Ende durchläuft (das 'warum' entschließt sich mir bisher nicht). Am Ende wird immer

Code: Select all

	items[ "Type" ] := "DATA"
ausgeführt, wobei items immer noch auf das Objekt verweist, das weiter oben ggfs. schon verändert wurde. Die vorherige Wertzuweisung für den Key Type wird damit überschrieben.

Dein Code ist vielleicht nicht kompliziert gemeint, ich habe aber durchaus Probleme damit, herauszufinden was er tun soll. ;)
just me
Posts: 5642
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Objekt array

06 Apr 2018, 08:20

Hi nnnik! ;)
User avatar
nnnik
Posts: 3527
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: Objekt array

06 Apr 2018, 08:21

Hi just me
Recommends AHK Studio
pramach
Posts: 49
Joined: 24 Jan 2018, 08:20

Re: Objekt array

06 Apr 2018, 08:46

Hi
erstmal Danke, aber ich bin mir nicht sicher ...

Code: Select all

items[ "Type" ] := "KIND"
ID += 1
AWS[ ID ] := items
Das müsste mir doch das Array 1 mit items (inkl Type = KIND) anlegen.

Das Nachfolgende

Code: Select all

items[ "Type" ] := "COLLECT"
ID += 1
AWS[ ID ] := items
dann dementsprechend das Array 2 mit gleichen items jedoch Type = COLLECT anlegen OHNE mir das bestehende Array 1 Type zu überschreiben.

Gleiches bei Group

Auch am Ende das

Code: Select all

	items[ "Type" ] := "DATA"
ID += 1
AWS[ ID ] := items
müsste mir ja wiederum ein neues Array element (4, 5, 6 ) mit Type = DATA.

Warum aber überschreibt er die AWS elemente 1-3 ?


Was möchte ich erreichen ?
Schlussendlich die TV_ADD ID's pro Tree Element in einem Array speichern um dann entsprechend dem Resultat von TV_GetSelection() die Daten aus dem Array in einer Subform je Level anzuzeigen.
Deshalb möchte ich ein (1) Array Element pro Tree Element.

Deshalb brauche ich auch kein "Else", Eigentlich ein simpler Gruppenbruch.


Soweit funktioniert ja auch was ich möchte, ausser eben das Problem des "Ueberschreibens" der Daten vorheriger Datensätze.
User avatar
nnnik
Posts: 3527
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: Objekt array  Topic is solved

06 Apr 2018, 08:55

Nein du musst wissen wenn Arrays oder Objekte in variablen oder anderen Arrays oder Objekten abgelegt werden werden sie nicht neu da hinein kopiert sondern, dass da einfach ein Verweis auf diesen originalen Array abgelegt.
Das bedeutet:

Code: Select all

a := [ "Nicht Hallo Welt!" ]
b := [a]
a.1 := "Hallo Welt!"
Msgbox  % b.1.1
Dieses Beispiel zeigt ganz gut, dass auf den ersten array nicht nur in der variable a verwiesen wird, sondern auch in b.1.
Den gleichen Effekt erlebst du bei dir. Um das zu umgehen musst du .clone() benutzen:

Code: Select all

a := [ "Nicht Hallo Welt!" ]
b := [a.clone()]
a.1 := "Hallo Welt!"
Msgbox  % b.1.1
Recommends AHK Studio
pramach
Posts: 49
Joined: 24 Jan 2018, 08:20

Re: Objekt array

06 Apr 2018, 08:55

P.S.
Wenn mann immer direkt nach der Anweisung

Code: Select all

AWS[ ID ] := items
eine msgbox einfügt, z.B.

Code: Select all

msgbox % "Kind: " . ID . " = " . AWS[ ID ].Type
Dann sieht man schön wie a) die ID hochgezählt wird und b) der richtige Type Wert vorhanden ist.

Schaut man sich nun aber nach der Anweisung

Code: Select all

AWS[ ID ] := items
den vorherigen Wert an

Code: Select all

msgbox % "Collect Prev: " . ( ID - 1) . " = " . AWS[ ID - 1 ].Type
steht da nun plötzlich der falsche Wert drin.

Bis anhin bin ich zumindest von dem Verhalten ausgegangen, das

Code: Select all

AWS[ ID ] := items
einen WERT zuweist und keine Referenz .... :D
pramach
Posts: 49
Joined: 24 Jan 2018, 08:20

Re: Objekt array

06 Apr 2018, 08:56

OK, ich versuche es mit dem Clone ..
pramach
Posts: 49
Joined: 24 Jan 2018, 08:20

Re: Objekt array

06 Apr 2018, 08:59

Yep, so funktioniert es.
Danke.

Return to “Ich brauche Hilfe”

Who is online

Users browsing this forum: Ragnar and 12 guests