ASCAN, ASORT "schachteln" ?

Alle Fragen um die Programmierung, die sich sonst nicht kategorisieren lassen. Von Makro bis Codeblock, von IF bis ENDIF

Moderator: Moderatoren

Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12913
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 46 Mal

ASCAN, ASORT "schachteln" ?

Beitrag von AUGE_OHR »

hi,

was mir gerade noch einfällt: Wenn ich in einem 2-Dimensionalen Array
das 1st und das 2nd Element sortiert haben will muss ich 2x ASORT
hintereinander benutzen. Kann man das "schachten" ?

Code: Alles auswählen

      { {"Auge","Ohr"} ;
        {"Donald","Duck"};
        {"Dagobert","Duck"};
        {"James", "Bond"}}

   ASORT(aPosi,,, {|X,Y| X[2] < Y[2] } ) // Nachname
   ASORT(aPosi,,, {|X,Y| X[1] < Y[1] } ) // Vorname
nun zu ASCAN :

Code: Alles auswählen

      { {"Auge","Ohr"} ;
        {"Donald","Duck"};
        {"Dagobert","Duck"};
        {"James", "Bond"}}

      { {"Donald","Duck","Tick" };
        {"Donald","Duck","Trick"};
        {"Donald","Duck","Track"} }
...
nStart1 := 1
DO WHILE  nPos1 > 0

  nPos1 := ASCAN(::aArray1,{|x| x[2] = "Duck"},nStart1))  
  IF nPos1 > 0
...
   nStart2 := 1
   DO WHILE nPos2 > 0
      nPos2 := ASCAN(::aArray2,{|x| x[1] = ::aArray1[nPos1,1] .AND. ;
                                    x[2] = ::aArray1[nPos1,2] },nStart2)
      IF nPos2 > 0
          AADD(::aResult, ::aArray2[nPos2,3])
          nStart2 := nPos2+1
      ELSE
          EXIT
      ENDIF 
   ENDDO 

  ENDIF
ENDDO 
kann man sowas nicht besser (schöner, kürzer) "schachteln" ?
gruss by OHR
Jimmy
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15710
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 73 Mal
Danksagung erhalten: 38 Mal
Kontaktdaten:

Re: ASCAN, ASORT "schachteln" ?

Beitrag von brandelh »

AUGE_OHR hat geschrieben:was mir gerade noch einfällt: Wenn ich in einem 2-Dimensionalen Array das 1st und das 2nd Element sortiert haben will muss ich 2x ASORT hintereinander benutzen
nein, auch wenn ich jetzt nicht absehen kann ob das Ergebnis passen würde (1. Durchlauf für 2. Sortierbegriff, danach 1. Sortierbegriff), ist ein Durchgang auf jeden Fall besser. Es kommt ja nur auf das Ergebnis des Vergleichsausdruckes an, dieser kann sehr komplex sein ...

Code: Alles auswählen

      { {"Auge","Ohr"} ;
        {"Donald","Duck"};
        {"Dagobert","Duck"};
        {"James", "Bond"}}

   ASORT(aPosi,,, {|X,Y| left(X[1]+space(50),50)+X[1] < left(Y[1]+space(50),50)+Y[1]  } )
 
AUGE_OHR hat geschrieben: nun zu ASCAN :

...

kann man sowas nicht besser (schöner, kürzer) "schachteln" ?
da verstehe ich nicht was du haben möchtest.
Suchst du dort Dubletten ?
Gruß
Hubert
Benutzeravatar
Martin Altmann
Foren-Administrator
Foren-Administrator
Beiträge: 16586
Registriert: Fr, 23. Sep 2005 4:58
Wohnort: Berlin
Hat sich bedankt: 116 Mal
Danksagung erhalten: 48 Mal
Kontaktdaten:

Beitrag von Martin Altmann »

Hallo Ihr zwei,
zum Thema aSort:

Code: Alles auswählen

Asort( aPosi,,, { | aX, aY | iif( aX[ 1 ] <> aY[ 1 ], aX[1] < aY[1], aX[2] < aY[2] ) } )
Und zum zweiten Thema: Abgesehen davon, dass Dein nPos2 nicht initialisiert ist (aber bestimmt nur hier beim Cut&Paste) könntest Du da vielleicht mit AEval() probieren...

Code: Alles auswählen

aEval(::aArray2, { |x| iif( ( x[1] == ::aArray1[nPos1,1]) .and. ( x[2] == ::aArray1[nPos1,2] ), aadd( ::aResult, x[3]), ) } )
So in etwa...

Viele Grüße,
Martin
:grommit:
Webseite mit XB2.NET und ausschließlich statischem Content in Form von HTML-Dateien: https://www.altem.de/
Webseite mit XB2.NET und ausschließlich dynamischem Content in Form von in-memory-HTML: https://meldungen.altem.de/

Mitglied der XUG Osnabrück
Vorsitzender des Deutschsprachige Xbase-Entwickler e. V.
Dieter
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 237
Registriert: Do, 14. Aug 2008 14:59
Wohnort: Straelen
Hat sich bedankt: 2 Mal
Danksagung erhalten: 3 Mal

Beitrag von Dieter »

Hallo,

ich bin der Meinung, dass man wie folgt 2-stufig sortieren muß:

Code: Alles auswählen

aArr=aSort(aArr,,,{ |x1,x2| x1[1]<x2[1] }
aArr=aSort(aArr,,,{ |x1,x2| IIF(x1[1]==x2[1] .AND. x1[2]<x2[2],.T.,.F.}
Viele Grüße

Dieter

Was man nicht versteht, besitzt man nicht.
Dieter
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 237
Registriert: Do, 14. Aug 2008 14:59
Wohnort: Straelen
Hat sich bedankt: 2 Mal
Danksagung erhalten: 3 Mal

Beitrag von Dieter »

Hallo,

mir ist ein Klammerfehler unterlaufen, richtig ist:

Code: Alles auswählen

aArr=aSort(aArr,,,{ |x1,x2| x1[1]<x2[1] }
aArr=aSort(aArr,,,{ |x1,x2| IIF(x1[1]==x2[1] .AND. x1[2]<x2[2],.T.,.F.)} 
Viele Grüße

Dieter

Was man nicht versteht, besitzt man nicht.
Dieter
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 237
Registriert: Do, 14. Aug 2008 14:59
Wohnort: Straelen
Hat sich bedankt: 2 Mal
Danksagung erhalten: 3 Mal

Beitrag von Dieter »

Hallo,

man sollte der Form halber ASORT immer groß schreiben. Entschuldigt bitte die Ungenauigkeit. :(
Viele Grüße

Dieter

Was man nicht versteht, besitzt man nicht.
Dieter
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 237
Registriert: Do, 14. Aug 2008 14:59
Wohnort: Straelen
Hat sich bedankt: 2 Mal
Danksagung erhalten: 3 Mal

Beitrag von Dieter »

Hallo,

:( :( :( :(

oh ist das peinlich, ich hoffe, dass jetzt alles richtig ist:

Code: Alles auswählen

aArr=ASort(aArr,,,{ |x1,x2| x1[1]<x2[1] })
aArr=ASort(aArr,,,{ |x1,x2| IIF(x1[1]==x2[1] .AND. x1[2]<x2[2],.T.,.F.)}) 
Viele Grüße

Dieter

Was man nicht versteht, besitzt man nicht.
mrparity
Rookie
Rookie
Beiträge: 17
Registriert: Mi, 06. Aug 2008 14:28

Beitrag von mrparity »

Zu ASORT:

Ein durchgang ist natürlich wesentlich schöner, vor allem, wenn man nichts an den Strings hin und her kopieren muss könnte das sogar in der halben zeit laufen, daher finde ich die Lösung von Martin gut.

Wenn du zwei durchläufe machst musst du aufpassen, dass dir der zweite durchlauf nicht deine erste Sortierung verhaut. Die frage ist also welchen Algorithmus verwendet Alaska und ist der stabil (= die Reihenfolge von schon sortierten Elementen ändert sich nach Sortierung nicht).

Bye.
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15710
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 73 Mal
Danksagung erhalten: 38 Mal
Kontaktdaten:

Beitrag von brandelh »

Dieter hat geschrieben:Hallo,

man sollte der Form halber ASORT immer groß schreiben. Entschuldigt bitte die Ungenauigkeit. :(
und wer sagt das jetzt ? :wink:

Dazu gibt es die verschiedensten Meinungen, GROSS schreiben die Meisten nur #DEFINE Ausdrücke.

Ich selbst schreibe Funktionen bzw. Methoden die unverändert sind:

1. Buchstabe immer klein, danach je Wortanfang 1 großer Buchstabe
2. eigene Funktionen bzw. Methoden immer je Wortanfang 1 großer Buchstabe
3. Variablen benenne ich nach Typ (ähnlich der ungarische Notation), wobei ich es nicht übertreibe (n = numerisch, d = Datum, c = String etc.)
Gruß
Hubert
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15710
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 73 Mal
Danksagung erhalten: 38 Mal
Kontaktdaten:

Beitrag von brandelh »

mrparity hat geschrieben:Ein durchgang ist natürlich wesentlich schöner, vor allem, wenn man nichts an den Strings hin und her kopieren muss könnte das sogar in der halben zeit laufen, daher finde ich die Lösung von Martin gut.
Martins Lösung ist auf jeden Fall schneller als meine, da die Stringänderungen im Vergleich zu direktem Vergleich deutlich langsamer sind. Da aSort aber insgesamt sehr schnell ist, weiß ich nicht ob man den Unterschied messen kann. Meine Lösung hat natürlich auch den Nachteil, dass man beim Auffüllen der Strings gut überlegen muss wie lange die Inhalte sind.

Ich persönlich mache halt viel mit Strings, daher liegen mir die mehr ;-)
Gruß
Hubert
Benutzeravatar
Martin Altmann
Foren-Administrator
Foren-Administrator
Beiträge: 16586
Registriert: Fr, 23. Sep 2005 4:58
Wohnort: Berlin
Hat sich bedankt: 116 Mal
Danksagung erhalten: 48 Mal
Kontaktdaten:

Beitrag von Martin Altmann »

Hallo Dieter,
keine Sorge - man muss nicht in zwei Durchgängen sortieren!
Die von mir vorgestellte Version funktioniert in meinem Programm so einwandfrei.

Viele Grüße,
Martin
:grommit:
Webseite mit XB2.NET und ausschließlich statischem Content in Form von HTML-Dateien: https://www.altem.de/
Webseite mit XB2.NET und ausschließlich dynamischem Content in Form von in-memory-HTML: https://meldungen.altem.de/

Mitglied der XUG Osnabrück
Vorsitzender des Deutschsprachige Xbase-Entwickler e. V.
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9394
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 105 Mal
Danksagung erhalten: 364 Mal
Kontaktdaten:

Beitrag von Tom »

Sorry for einmischeling, aber meines Erachtens geht das mit der Sortierung sehr viel einfacher:

Code: Alles auswählen

aSort(aArray,,,{|aY1,aY2|aY1[1]+aY1[2] < aY2[1]+aY2[2]})
Dies sortiert nach Eintrag eins plus Eintrag zwei, also Name+Vorname. Notfalls müsste man mit PadR() noch den Ausdruck vor dem Pluszeichen auf eine konkrete Länge füllen. Auf diese Weise lassen sich in mehrdimensionalen Arrays beliebig viele Spalten als Sortierausdruck kombinieren.
Herzlich,
Tom
mrparity
Rookie
Rookie
Beiträge: 17
Registriert: Mi, 06. Aug 2008 14:28

Beitrag von mrparity »

brandelh hat geschrieben: Martins Lösung ist auf jeden Fall schneller als meine, da die Stringänderungen im Vergleich zu direktem Vergleich deutlich langsamer sind. Da aSort aber insgesamt sehr schnell ist, weiß ich nicht ob man den Unterschied messen kann. Meine Lösung hat natürlich auch den Nachteil, dass man beim Auffüllen der Strings gut überlegen muss wie lange die Inhalte sind.
Schneller sollte Martins Lösung auf jeden Fall sein, aber je nach dem, wie die Alaska Leute den +-Operator implementiert haben geht es. Wenn ich das machen müsste würde ich (falls ich auf Performance achte) an Alaskas stelle keine Strings durch die gegend kopieren, sondern einfach als lineare Liste aneinander hängen.

Ob ASORT schnell ist liegt ja im Auge des Bertachters. Schneller als n*log(n) wird es in keinem Falle sein. Je schneller ASORT aber ist, desto besser kann man den Unterschied messen, da der zeitliche prozentuale Anteil der an der Stringoperation beteiligten Funktionen natürlich größer wird.

Have a nice day
Benutzeravatar
Martin Altmann
Foren-Administrator
Foren-Administrator
Beiträge: 16586
Registriert: Fr, 23. Sep 2005 4:58
Wohnort: Berlin
Hat sich bedankt: 116 Mal
Danksagung erhalten: 48 Mal
Kontaktdaten:

Beitrag von Martin Altmann »

Hallo Tom,
Tom hat geschrieben:Sorry for einmischeling,
nö - kümmere Dich lieber um die neue Boardversion :!: :lol: :wink:
Tom hat geschrieben:aber meines Erachtens geht das mit der Sortierung sehr viel einfacher:

Code: Alles auswählen

aSort(aArray,,,{|aY1,aY2|aY1[1]+aY1[2] < aY2[1]+aY2[2]})
Yup - hatte ich früher auch so im Einsatz, geht auch. Und wahrscheinlich auch ein wenig schneller, als meine oben skizzierte Variante, da keine if-Abfrage nötig ist.
Aber es gibt auch Situationen, in denen das nicht geht. Wenn z.B. nach mehreren Spalten in Abhängigkeit sortiert werden soll (also nach der dritten Spalte absteigend, so lange die ersten beiden Spalten identisch sind - ansonsten nach den ersten beiden Spalten aufsteigend)...

Viele Grüße,
Martin
:grommit:
Webseite mit XB2.NET und ausschließlich statischem Content in Form von HTML-Dateien: https://www.altem.de/
Webseite mit XB2.NET und ausschließlich dynamischem Content in Form von in-memory-HTML: https://meldungen.altem.de/

Mitglied der XUG Osnabrück
Vorsitzender des Deutschsprachige Xbase-Entwickler e. V.
Dieter
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 237
Registriert: Do, 14. Aug 2008 14:59
Wohnort: Straelen
Hat sich bedankt: 2 Mal
Danksagung erhalten: 3 Mal

Beitrag von Dieter »

Hallo Martin,

ich hatte vorher testen sollen, dein Code ist richtig. Ich habe wieder etwas gelernt! In dem Zusammenhang scheint es noch einfacher zu funktioniern:

Code: Alles auswählen

ASort(aArr,,,{ |x1,x2| x1[1]<x2[1] })
Das funktioniert bei mir einwandfrei. Auch die Vornamen werden richtig sortiert! Warum es funktioniert, weiß wahrscheinlich nur Alaska.
Viele Grüße

Dieter

Was man nicht versteht, besitzt man nicht.
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15710
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 73 Mal
Danksagung erhalten: 38 Mal
Kontaktdaten:

Beitrag von brandelh »

Dieter hat geschrieben: In dem Zusammenhang scheint es noch einfacher zu funktioniern:

Code: Alles auswählen

ASort(aArr,,,{ |x1,x2| x1[1]<x2[1] })
Das funktioniert bei mir einwandfrei. Auch die Vornamen werden richtig sortiert! Warum es funktioniert, weiß wahrscheinlich nur Alaska.
Wenn diese Funktion dein Array richtig sortiert, dann nur deshalb weil du entweder keine gleichen Nachnahmen hast, oder aber die Gleichen zufällig in der richtigen Reihenfolge liegen.

So sortiert man eindeutig nur nach einer Spalte.

@TOMs Version,

wenn die Namen nicht mit Leerzeichen aufgefüllt sind (dazu habe ich mein Konstrukt benutzt), wird deine Variante die Vornamen in der Nachnamen Spalte mitbenutzen. Wenn die Strings alle gleich lang sind stimmts natürlich:

"Meier","Xenia"
"Meierhausen","Kurt"

sollten eigentlich so sortiert werden, da "Meier" kleiner als "Meierhausen" ist,

"Meier","Xenia"
"Meierhausen","Kurt"

aber bei + Sortierung wird daraus

"MeierhausenKurt"
"MeierXenia"

Somit ist Martins Lösung weiterhin die optimierteste, allerdings wird es bei mehr Kriterien sehr schwer mit IIF() ... daher bleibe ich bei meiner Version oder man baut gleich eine richtige Funktion ;-)
Gruß
Hubert
Benutzeravatar
Martin Altmann
Foren-Administrator
Foren-Administrator
Beiträge: 16586
Registriert: Fr, 23. Sep 2005 4:58
Wohnort: Berlin
Hat sich bedankt: 116 Mal
Danksagung erhalten: 48 Mal
Kontaktdaten:

Beitrag von Martin Altmann »

Hallo Hubert,
brandelh hat geschrieben:...allerdings wird es bei mehr Kriterien sehr schwer mit IIF() ...
yup - hier mal ein weiteres Beispiel aus der Praxis:

Code: Alles auswählen

asort( ptag,,, {|aX,aY| iif( aX[ 1 ] <> aY[ 1 ], aX[1] < aY[1], iif( aX[ 2 ] <> aY[ 2 ], aX[2] < aY[2], aX[ 3 ] < aY[ 3 ] ) ) } )
Viele Grüße,
Martin
:grommit:
Webseite mit XB2.NET und ausschließlich statischem Content in Form von HTML-Dateien: https://www.altem.de/
Webseite mit XB2.NET und ausschließlich dynamischem Content in Form von in-memory-HTML: https://meldungen.altem.de/

Mitglied der XUG Osnabrück
Vorsitzender des Deutschsprachige Xbase-Entwickler e. V.
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12913
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 46 Mal

Beitrag von AUGE_OHR »

hi,
Martin Altmann hat geschrieben: zum Thema aSort:

Code: Alles auswählen

Asort( aPosi,,, { | aX, aY | iif( aX[ 1 ] <> aY[ 1 ], aX[1] < aY[1], aX[2] < aY[2] ) } )
darauf bin ich noch nicht gekommen, mal ausprobieren.
Martin Altmann hat geschrieben: Und zum zweiten Thema: Abgesehen davon, dass Dein nPos2 nicht initialisiert ist (aber bestimmt nur hier beim Cut&Paste) könntest Du da vielleicht mit AEval() probieren...

Code: Alles auswählen

aEval(::aArray2, { |x| iif( ( x[1] == ::aArray1[nPos1,1]) .and. ( x[2] == ::aArray1[nPos1,2] ), aadd( ::aResult, x[3]), ) } )
So in etwa...
yup das musste gehen.

Danke
gruss by OHR
Jimmy
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9394
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 105 Mal
Danksagung erhalten: 364 Mal
Kontaktdaten:

Beitrag von Tom »

@Hubert: Ich fahre mit meiner Version sehr gut, weil sie kompakt und sehr lesbar ist (ich habe sie auch gerade mal mit einer Million Arrayzeilen getestet - es ist nicht signifkant langsamer als ein ASort ohne PadR() auf nur einer Spalte). Zudem arbeiten wir alle hier ja mit Tabellen, die diskrete Feldlängen verlangen (ich könnte keinen Sinn darin erkennen, Inhalte von Memofeldern auf diese Art zu sortieren), weshalb so gut wie alle Texte, die dieserart in Arrays gesammelt werden könnten, ohnehin längenmäßig limitiert sind. Aber ich will niemanden überreden ... viele Wege führen nach Rom. Leider. :D
Herzlich,
Tom
Dieter
Rekursionen-Architekt
Rekursionen-Architekt
Beiträge: 237
Registriert: Do, 14. Aug 2008 14:59
Wohnort: Straelen
Hat sich bedankt: 2 Mal
Danksagung erhalten: 3 Mal

Beitrag von Dieter »

Hallo Hubert,


du hast geschrieben:
Wenn diese Funktion dein Array richtig sortiert, dann nur deshalb weil du entweder keine gleichen Nachnahmen hast, oder aber die Gleichen zufällig in der richtigen Reihenfolge liegen.

So sortiert man eindeutig nur nach einer Spalte.
Teste bitte die folgenden Code:

Code: Alles auswählen

PROCEDURE main
LOCAL aArr
aArr={{"Kreuzer", "Dieter"},{"Test", "Dieter"}, {"Duck", "Donald"}, {"Test", "Andreas"}, {"Duck", "Dagobert"},{"Kreuzer","Andreas"}}
//aArr=Asort( aArr,,, { | aX, aY | iif( aX[ 1 ] <> aY[ 1 ], aX[1] < aY[1], aX[2] < aY[2] ) } ) // Martin`s Lösung
aArr=ASort(aArr,,,{ |x1,x2| x1[1]<x2[1] })

? aArr

WAIT
RETURN

// Ergebnis:
// {{Duck, Dagobert}, {Duck, Donald}, {Kreuzer, Andreas}, {Kreuzer, Dieter}, {Test, Andreas}, {Test, Dieter}}
Viele Grüße

Dieter

Was man nicht versteht, besitzt man nicht.
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12913
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 46 Mal

Beitrag von AUGE_OHR »

hi,

so und wie kombiniere ich beides wenn ich folgendes Array habe :

Code: Alles auswählen

{{212,3};
 {212,3};
 {212,3};
 {213,1};
 {213,1} }
und wissen will welche Kombination am "öftesten" vorkommt, also hier
die {212,3} 3x ?

... ich will ja keine Schleife schreiben wo ich jedes Element "Schritt für
Schritt" auswerten müsste ( ... das kann ich )
gruss by OHR
Jimmy
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9394
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 105 Mal
Danksagung erhalten: 364 Mal
Kontaktdaten:

Beitrag von Tom »

Hallo, Dieter.

Das ist Zufall. Wenn Du die Vornamen bei den beiden "Test" austauschst, bekommst Du dieses Ergebnis:

{{"Duck", "Dagobert"}, {"Duck", "Donald"}, {"Kreuzer", "Andreas"}, {"Kreuzer", "Dieter"}, {"Test", "Dieter"}, {"Test", "Andreas"}}

ASort(aArr,,,{ |x1,x2| x1[1]<x2[1] }) sortiert wirklich nur nach der ersten Spalte. Was mit der zweiten (und allen weiteren) geschieht, hat mit der Arbeitsweise des Algorithmus' zu tun.
Herzlich,
Tom
Benutzeravatar
Martin Altmann
Foren-Administrator
Foren-Administrator
Beiträge: 16586
Registriert: Fr, 23. Sep 2005 4:58
Wohnort: Berlin
Hat sich bedankt: 116 Mal
Danksagung erhalten: 48 Mal
Kontaktdaten:

Beitrag von Martin Altmann »

Hallo Dieter,
Hubert braucht Deinen Code nicht zu probieren, da er das von Dir beobachtete Ergebnis liefert - das war mir damals auch aufgefallen.
Trotzdem hat Hubert Recht mit seiner Aussage, dass Dein Beispiel definitv nur nach einer Spalte sortiert - zumindest sagst Du ihm ja nichts anderes!
Und wenn der Befehl bei Gleichheit der Kriterien automatisch die nächste Spalte berücksichtigt, so ist das ein undokumentiertes Verhalten. Darauf würde ich mich nie verlassen!
Also immer bewusst die anderen Spalten explizit mit angeben - spätestens dann, wenn nach ihnen absteigend sortiert werden soll, kommt man da eh' nicht drum herum!

Jimmy,
nur über ein Konstrukt nach dem folgenden Schema:

Code: Alles auswählen

aErg:={}
aEval( aArray, {|x| zaehl( x, @aErg ) } )
nMax := 0
aMax := {}
nJ := len( aErg )
for nI := 1 to nJ
  if nMax < aErg[ nI, 2 ]
    nMax := aErg[ nI, 2 ]
    aMax := aClone( aErg[ nI, 1 ] )
  endif
next
....
procedure zaehl( aEle, aErgebnis )
local nI
nI := ascan( aErgebnis, { |a| a[ 1 ] == aEle } )
if nI > 0
  aErgebnis[ nI, 2 ]++
else
  aAdd( aErgebnis, { aEle, 1 } )
endif
return
Viele Grüße,
Martin
:grommit:
Webseite mit XB2.NET und ausschließlich statischem Content in Form von HTML-Dateien: https://www.altem.de/
Webseite mit XB2.NET und ausschließlich dynamischem Content in Form von in-memory-HTML: https://meldungen.altem.de/

Mitglied der XUG Osnabrück
Vorsitzender des Deutschsprachige Xbase-Entwickler e. V.
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12913
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 46 Mal

Beitrag von AUGE_OHR »

hi,
Martin Altmann hat geschrieben: Jimmy,
nur über ein Konstrukt nach dem folgenden Schema:
Tja sowas hatte ich befürchtet. Ich hab nun sowas

Code: Alles auswählen

aLogic   := { { WR_UP   ,0} ,;
              { WR_RIGHT,0} ,;
              { WR_DOWN ,0} ,;
              { WR_LEFT ,0} }

iMax := LEN(aNextWay)
FOR i:= 1 TO iMax
   TestWay := aNextWay[i,2]

   DO CASE
      CASE TestWay = WR_UP    ; aLogic[WR_UP   ,2]++
      CASE TestWay = WR_RIGHT ; aLogic[WR_RIGHT,2]++
      CASE TestWay = WR_DOWN  ; aLogic[WR_DOWN ,2]++
      CASE TestWay = WR_LEFT  ; aLogic[WR_LEFT ,2]++
   ENDCASE
NEXT
also auch "nur" ein Zähler in einer FOR / NEXT "Schleife" ...

Aber ich hab in meinen Fall nun wieder "Logic" ansetzten können

Code: Alles auswählen

iMax := LEN(aLogic)
IF iMax > 0
   //
   // old Direction
   //
   TestWay := ::nDirection
   //
   // oppsite Way
   //
   TestWay := TestWay+2
   IF TestWay > 4
      TestWay := TestWay-4
   ENDIF
   //
   // remove "go back"
   //
   iMax := LEN(aLogic)
   FOR i := iMax TO 1 STEP -1
      IF aLogic[i,1] = TestWay
         AREMOVE(aLogic,i)
      ENDIF
   NEXT
durch das AREMOVE() konnte ich nun alle aus dem Array entfernen die
"zurück laufen" und somit habe ich in meinem Demo z.Z. nur noch eine
Richtung (der Rest wurde vorher "ausgefiltert").

Nun muss ich mal ein anderes Layout wählen um zu sehen wie er dann
reagiert aber das Prinzip (scheint) zu funktionieren !!!

Was mich nun interessieren würde wäre der "ganze Weg" durch das
Labyrinth den z.Z, "denke" ich nur 2 Schritte vorraus.

Da das ganze nun mit Arrays, ASCAN() und ASORT() läuft hatte ich den
Thread angefangen den meine 2 Schritte sind noch "procedural" und ich
müsste es recusive machen deshalb das "schachteln".

Ich werde mal versuchen das ganze jetzt recusive zu machen und werde
zwecks optimierung dann wiede damit ankommen. Gerade bei recursiven
Functionen macht das sicherlich viel aus.

*** Gedankensprung ***

Auch denke ich statt "procedural" könnte man vielleicht je einen Thread
für eine "neuen Weg" starten damit Xbase++ gleichzeitg "rechts" und
"links" durch suchen werden kann...

Frage : wieviele Thread hab ihr bislang max. laufen lassen ?

... ich bin mir nicht sicher wie gross der "Suchbaum" wird und ob ich max
13*4*10*4 Threads gleichzeigt laufen lassen kann :)

*** eof ***

ok nun zurück : ASORT() haben wir nun hier gehört aber wie könnte man
recursive den Code von Martin für ASCAN() erweitern ?

Code: Alles auswählen

aEval(::aArray2, { |x| iif( ( x[1] == ::aArray1[nPos1,1]) .AND. ;
                            ( x[2] == ::aArray1[nPos1,2] ),;
                             aadd( ::aResult, x[3]), ) } )
RETURN ::aResult
Das Ergebniss eines ASCAN soll der nStart Wert des nächsten Arrays sein
deshalb denke ich an recursive
... oder sollte ich mir den Codeblock als String zusammen stellen und den
dann AEVAL(en) ?
gruss by OHR
Jimmy
Benutzeravatar
Martin Altmann
Foren-Administrator
Foren-Administrator
Beiträge: 16586
Registriert: Fr, 23. Sep 2005 4:58
Wohnort: Berlin
Hat sich bedankt: 116 Mal
Danksagung erhalten: 48 Mal
Kontaktdaten:

Beitrag von Martin Altmann »

Nun,
Martin Altmann hat geschrieben:

Code: Alles auswählen

....
nMax := 0
aMax := {}
nJ := len( aErg )
for nI := 1 to nJ
  if nMax < aErg[ nI, 2 ]
    nMax := aErg[ nI, 2 ]
    aMax := aClone( aErg[ nI, 1 ] )
  endif
next
...
Zumindest den Teil mit der Ergebnissuche am Ende kann man noch weiter optimieren:

Code: Alles auswählen

aSort( aErg,,, {|aX,aY| aX[2] > aY[2] } )
aMax := aClone( aErg[ 1, 1 ] )
Viele Grüße,
Martin
:grommit:
Webseite mit XB2.NET und ausschließlich statischem Content in Form von HTML-Dateien: https://www.altem.de/
Webseite mit XB2.NET und ausschließlich dynamischem Content in Form von in-memory-HTML: https://meldungen.altem.de/

Mitglied der XUG Osnabrück
Vorsitzender des Deutschsprachige Xbase-Entwickler e. V.
Antworten