AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Datenbanken Delphi Datensätze zufällig anzeigen, aber alle nur einmal
Thema durchsuchen
Ansicht
Themen-Optionen

Datensätze zufällig anzeigen, aber alle nur einmal

Ein Thema von Susanne · begonnen am 9. Apr 2005 · letzter Beitrag vom 10. Apr 2005
Antwort Antwort
Seite 1 von 2  1 2      
Susanne

Registriert seit: 21. Mai 2004
Ort: Lage
232 Beiträge
 
Delphi 2005 Professional
 
#1

Datensätze zufällig anzeigen, aber alle nur einmal

  Alt 9. Apr 2005, 21:49
Datenbank: Access • Zugriff über: ADO
hallo,

ich habe eine Datenbank in der Datensätze drin sind. Dann habe ich ein Programm, dort mache ich eine Adoquery und frage bestimmte Datensätze ab. Nun habe ich als ergebnis von RecordCount z.B. 10 Datensätze.
Diese sollen nun nacheinander in zufälliger Reihenfolge in meinem Programm angezeigt werden. Mein Problem ist nun, wie ich dies hinkriege.

Was ich bisher habe ist, dass ich im OnCreate-Ereignis Randomize aufrufe und später in meinem Programm, wenn ich meine adoquery ausgeführt habe und die Datensätze anzeigen will dieses:


Delphi-Quellcode:
   z:= RandomRange(1, adoquery1.RecordCount);
   //nun müsste ich auf den z. Datensatz zugreifen und diesen anzeigen
   //kann ich dann diesen Datensatz aus der Query rausschmeissen, ohne dass er in der
   //DB rausgeschmissen wird?
   //so müsste ich doch erreichen, dass jeder Datensatz dann nur einmal angezeigt wird
Ich hoffe, mir kann da jemand weiterhelfen, oder hat einen besseren vorschlag, wie ich das Problem lösen kann. Ich probiere ich schon den halben Tag daran rum und krieg es nicht gebacken
Susanne
  Mit Zitat antworten Zitat
Benutzerbild von Sharky
Sharky

Registriert seit: 29. Mai 2002
Ort: Frankfurt
8.251 Beiträge
 
Delphi 2006 Professional
 
#2

Re: Datensätze zufällig anzeigen, aber alle nur einmal

  Alt 10. Apr 2005, 05:10
Hai Susanne,

der einzige Weg der mir einfällt ist der über .RecNo die Datensätze in einer zufälligen Reihenfolge anzusprechen.
Du müsstest also deine Record-Nummern (die ja nur eine zusammenhängende Liste von Integern sind) in eine zufällige Reihenfolge bringen.
Dafür kannst Du z.B. diesen Code von Hagen aus dem Lotto-Thread verwenden.

Dann kannst Du so die Datensätze in einer zufälligen Reihenfolge ansprechen.
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var
  Sortiert, Zufall: TZahlen;
  anzahl : Integer;
  ndx: Integer;
begin
  anzahl := Query1.RecordCount;
  Lotto(Sortiert, Zufall, anzahl, anzahl);
  for ndx := 0 to High(Zufall) do
  begin
    Query1.RecNo := Zufall[ndx];
// Mache etwas mit dem aktuellen
// Datensatz
  end;
end;
Ich habe den Code von Hagen gewählt weil Du dann ganz einfach auch sagen kannst: "Ich möchte von meinen 10 Datensätzen 5 Stück in einer zufälligen Reihenfolge haben).
Stephan B.
"Lasst den Gänsen ihre Füßchen"
  Mit Zitat antworten Zitat
Benutzerbild von negaH
negaH

Registriert seit: 25. Jun 2003
Ort: Thüringen
2.950 Beiträge
 
#3

Re: Datensätze zufällig anzeigen, aber alle nur einmal

  Alt 10. Apr 2005, 11:32
Da man X aus X Records zufällig sortiert haben möchte ist mein Code eine relativ ineffiziente Lösung. Es geht besser.

Delphi-Quellcode:

procedure ListeRecords:
var
  Seed,I: Integer;
begin
  Seed := RandSeed; // Zufallsstartwert speichern
  for J := 0 to RecordCount -1 do
  begin
    RandSeed = Seed;
    for I := 0 to RecordCount -1 do
      if Random(RecordCount) = J then
        PrintRecord(I);
  end;
end;
Probiere obigen Code einfach aus und analysiere ihn, ich glaube das ist einfacher als ihn jetzt hier umständlich erklären zu müssen. Die Schleifen laufen zwar mit RecordCount^2 Komplexität, allerdings werden nur RecordCount Datensatzzugriffe ausgeführt. Da die Laufzeitgeschwindigkeit der Random() Funktion vernachlässigenbar ist, stellt das kein Peformanceproblem dar. Vorteil ist das man ohne Speichertabellen, Sortierungen etc. auskommt.

Gruß Hagen
  Mit Zitat antworten Zitat
Benutzerbild von Sharky
Sharky

Registriert seit: 29. Mai 2002
Ort: Frankfurt
8.251 Beiträge
 
Delphi 2006 Professional
 
#4

Re: Datensätze zufällig anzeigen, aber alle nur einmal

  Alt 10. Apr 2005, 11:37
Zitat von negaH:
Da man X aus X Records zufällig sortiert haben möchte ist mein Code eine relativ ineffiziente Lösung....
Hai,

darum habe ich ja in meinem Abschlusssatz geschrieben das ich deinen Code vorschlage weil man dann auch, ohne Änderung des Codes, nur x aus y Records zufällig anzeigen kann
Oder habe ich deinen Code aus dem Lotto Thread da falsch verstanden?
Stephan B.
"Lasst den Gänsen ihre Füßchen"
  Mit Zitat antworten Zitat
Benutzerbild von negaH
negaH

Registriert seit: 25. Jun 2003
Ort: Thüringen
2.950 Beiträge
 
#5

Re: Datensätze zufällig anzeigen, aber alle nur einmal

  Alt 10. Apr 2005, 11:44
Nein hast du nicht
Und wenn man es so will bin ich exakt deiner Meinung, mein Lottocode wäre die beste und effizienteste mir bekannte Alternative, ausgenommen eben mein obiger Vorschlag, denn auch dieser kann X aus Y Records aussortieren. Dazu wird einfach die äussere Schleife verkürzt. Es hängt nun nur von der Geschwindigkeit der Funktion Random() ab ob man obigen Source oder meinen Lottocode benutzen sollte. Obiger Code hat noch einen klitzekleinen Vorteil: man kann auch ohne Kenntnis der Recordnummer die Records aussortieren. Die innere Schleife I geht dann einfach per DataSet.Next über die Datenbank durch.

Gruß Hagen
  Mit Zitat antworten Zitat
Robert Marquardt
(Gast)

n/a Beiträge
 
#6

Re: Datensätze zufällig anzeigen, aber alle nur einmal

  Alt 10. Apr 2005, 11:45
Das ist zuerst ein kombinatorisches Problem. Letztlich die Umkehrung der Sortierung.
Die einfachste Methode ist daher eine Liste der RecNo's zu erstellen und sie zu verwuerfeln.
10 x Anzahl der Datensaetze je zwei zufaellig gewaehlte Elemente der Liste zu tauschen sollte mehr als ausreichend sein.
Danach die Liste von vorn nach hinten abarbeiten. Das ist nur problematisch wenn die Liste sehr lang ist.
  Mit Zitat antworten Zitat
Benutzerbild von negaH
negaH

Registriert seit: 25. Jun 2003
Ort: Thüringen
2.950 Beiträge
 
#7

Re: Datensätze zufällig anzeigen, aber alle nur einmal

  Alt 10. Apr 2005, 11:51
@Robert,

nun schaue dir mal meinen Lottocode genauer an, er vermeidet nämlich diese Methode und benötigt nur eine Liste von X Elementen wenn man X aus Y Records benötigt. Desweiteren ist mein obiger Vorschlag eine Lösung die ohne diese Liste auskommt. Beide Vorschläge, der Lottocode und der obige Vorschlag, lösen exakt dieses kombinatorische Problem das du ansprichst. Aber eben ohne deine programmtechnische Lösung des Problemes und sie sind, einmal verstanden, auch die einfachste Lösung

Übrigens fällt mir da noch ein Vorteil zum obigen Code ein. Er kann die Records partitioniert ausgeben. D.h. die Schlefe J kann durch aus auch von X nach Y laufen, wobei X > 0 und Y < Recordcount ist. Man kann so also Häppchenweise aus einem Set von Datensätzen nacheinander Blöcke anzeigen, ohne Wiederholungen zu bekommen.

Gruß Hagen
  Mit Zitat antworten Zitat
Robert Marquardt
(Gast)

n/a Beiträge
 
#8

Re: Datensätze zufällig anzeigen, aber alle nur einmal

  Alt 10. Apr 2005, 11:58
Ich wollte es ja nicht richtig loesen sondern einfach
Die Originalfrage will ja nur alle Datensaetze anzeigen, keine Auswahl daraus.
Im uebrigen ist es immer interessant zu erwaehnen das es eine Umkehrung von Sortieren gibt.
  Mit Zitat antworten Zitat
Benutzerbild von negaH
negaH

Registriert seit: 25. Jun 2003
Ort: Thüringen
2.950 Beiträge
 
#9

Re: Datensätze zufällig anzeigen, aber alle nur einmal

  Alt 10. Apr 2005, 12:00
@Robert, ich weis worauf du hinaus wolltest, ich behaupte aber das es eben nicht die einfachste Lösung ist. Es ist in fakt die intuitivste Lösung, aber nicht die einfachste

Gruß Hagen
  Mit Zitat antworten Zitat
Benutzerbild von negaH
negaH

Registriert seit: 25. Jun 2003
Ort: Thüringen
2.950 Beiträge
 
#10

Re: Datensätze zufällig anzeigen, aber alle nur einmal

  Alt 10. Apr 2005, 12:56
Delphi-Quellcode:
function RandomUnique(Index,Count: Integer; Order: Integer = $12345678): Integer;
var
  Seed,I,J: Integer;
begin
  Seed := RandSeed;
  try
    for I := 0 to Count -1 do
    begin
      RandSeed := Order;
      for J := 0 to Count -1 do
        if Random(Count) = I then
          if Index = 0 then
          begin
            Result := J;
            Exit;
          end else Dec(Index);
    end;
    Result := 0; // dieser Fall kann eigentlich nie eintreten
  finally
    RandSeed := Seed;
  end;
end;

Obige Funktion kannst du so einsetzen wie gewünscht:

Delphi-Quellcode:

ListOrder := Random(MaxInt);

// 1. Datensatz
DataSet.RecNo := RandomUnique(0, DataSet.RecordCount, ListOrder);
// 2. Datensatz
DataSet.RecNo := RandomUnique(1, DataSet.RecordCount, ListOrder);
// 3. Datensatz
DataSet.RecNo := RandomUnique(2, DataSet.RecordCount, ListOrder);
Der Parameter "Order" stellt dabei sowas wie eine eindeutige Nummer zur Reihenfolge der erzeugten Nummern dar. Er muss für jeden Aufruf der Funktion die zur gleichen Liste stammt auch immer gleich sein.

Das Verfahren ansich ist echt simpel. Durch die Manpulation von RandSeed == Startwert des Zufallsgenerators erzeugt man zu jedem Zeitpunkt ausgehend von Order immer wieder die gleiche Liste von Zufallszahlen (dafür ist ja auch ein Pseudozufallsgenerator und RandSeed gedacht ) Wir müssen also nun nur noch die "Filterung" für das auszuwählende Element der so produzierten Zufallszahlenliste vornehmen.
Man muß halt Count^2 mal durch diese Liste durchgehen um eine Eindeutigkeit zu produzieren, da unsere Random() Funktion eben nicht eindeutige Nummern erzeugt.

Nungut, obige Funktion sollte somit auch diese häufig gestellte Frage beantworten.

Gruß Hagen
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 09:20 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz