2017-04-14 6 views
0

Sie müssen per Zufall mit LINQ bestellen und ich kann GUID.NewGuid() nicht verwenden, ich brauche etwas wie diese: .OrderBy (x => "somestring").Linq Reihenfolge nach dem Zufallsprinzip ohne GUID

eine mobile App soll eine zufällige Zeichenfolge generieren und rufen Sie mein WebApi und weil ich Paging Mobile App beibehalten wird die gleiche Zufallszeichenfolge aber eine andere Seitennummer senden, so dass jedes Mal, wenn es diese zufällige Zeichenfolge Reihenfolge gesendet wird, sollte aber identisch sein verschiedene überspringen ....

Wie ist das möglich? wenn nicht eine Zeichenkette, aber möglicherweise eine Zahl oder etwas, das für jede linq Frage behoben wird.

Edit:

ist dies die WebAPI

[Route("GetChannels/{id}/{word}/{page}/{randomstring}")] 
public IEnumerable<Channels> GetChannels(int id, string word, int page, string randomstring) 
    { 

    ... 

    if (canPage) 
     {     
      var channels = db.Channels.Where(x => (id == 0) || (x.CategoryId == id)) 
      .Where(q => word == "0" || 
      (q.Title.Contains(word) || q.Desc.Contains(word))) 
      .OrderBy(x => randomstring).Skip(skip).Take(pageSize).ToList(); 
     } 

... 
+0

Können Sie Ihrer Problembeschreibung einige Interpunktionen hinzufügen? Wie es derzeit geschrieben ist, ist es nicht klar, was Sie jetzt haben, wie Sie api anrufen, und was Sie erwarten, –

+0

Kann ich fragen, warum Sie GUID wollen? Ich denke, die Jon Skeet Antwort verwendet GUIDs –

+0

@SergeyBerezovskiy, fügte ich weitere Details hinzu – farhang67

Antwort

1

Wenn Sie in zufälliger Reihenfolge zurückgehen wollen, aber das um die gleiche sein, wenn Sie senden die gleiche Zeichenfolge vom Client, dann können Sie Random Klasse verwenden, um Pseudozufallsreihenfolge zu erhalten. Dieser Zufallsgenerator kann seed annehmen - ein Wert, der verwendet wird, um den Startwert der Pseudozufallssequenz zu berechnen. So string Sie übergeben Sie können es verwenden Hash-Code Integer-Wert für Saatgut zu erhalten:

 var seed = randomstring.GetHashCode(); 
     var random = new Random(seed); 

     var channels = db.Channels 
      .Where(x => (id == 0) || (x.CategoryId == id)) 
      .Where(q => word == "0" || (q.Title.Contains(word) || q.Desc.Contains(word))) 
      .AsEnumerable() // randomizing should happen on client side 
      .OrderBy(x => random.Next()) 
      .Skip(skip) 
      .Take(pageSize) 
      .ToList();  
+0

Eine nette Lösung, aber eine Einschränkung ist, dass, wenn sich die Liste überhaupt zwischen dem ersten Anruf und irgendwelchen folgenden paging Anrufen ändert, die Liste total geändert wird. Wenn du also etwas ansiehst, das sich oft ändert, wird das nicht sehr gut funktionieren. Da die meisten Datenbanken keine Reihenfolge garantieren, wenn kein 'orderby' angegeben ist, ist es durchaus möglich, dass dieser Wert ausgeglichen wird, wenn keine Datensätze geändert werden ... –

+0

Sie können das spätere Problem beheben, indem Sie' .OrderBy (x = > x.id) 'vor dem' .AsEnumerable() '. –

+0

@RobertMcKee, leider wird dies nicht funktionieren. Sie können nicht mit dem Hinzufügen von Elementen und Speichern der ursprünglichen Reihenfolge der Originalartikel umgehen. Z.B. Du hast Gegenstände '1,2,3'. Die wurden als '2,1,3' bestellt. Ein weiterer Artikel wurde hinzugefügt. Sie möchten die ursprüngliche Reihenfolge beibehalten und '2,1,3,4' zurückgeben.Der nächste Artikel kommt. Sie möchten die ursprüngliche Reihenfolge beibehalten und erhalten '2,1,3,4,5'. I.e. Alle zukünftigen Gegenstände werden nicht gemischt. Sie werden in der Reihenfolge zurückgegeben, in der sie hinzugefügt wurden. –

0

etwas Versuchen Sie, wie dieses

Random rand = new Random(); 
      List<string> input = new List<string>(); 
      var results = input.Select(x => new { x = x, r = rand.Next() }).OrderBy(x => x.r).Select(x => x.x); 
1

Unter @ Sergeys bereits ausgezeichneten Antwort und Lösung von einer paar kleineren Eckfällen:

var channels = db.Channels.AsQueryable(); 

    #region filtering 
     if (id!=0) 
     channels = channels.Where(x=>x.CategoryId == id); 
     if (word!="0") 
     channels = channels.Where(x=>x.Title.Contains(word) || x.Desc.Contains(word)); 
    #endregion filtering 

    #region server-side ordering 
     channels = channels.OrderBy(x=>x.id); 
    #endregion server-side ordering 

    #region client-side ordering 
     var seed = randomstring.GetHashCode(); 
     var random = new Random(seed); 
     var channelList = channels.ToList(); // force client side 
     var maxid = channelList.Select(x=>id).Max(); 
     var keys = Enumerable 
     .Range(0,maxid) 
     .ToDictionary(x=>x,x=>random.Next()); 

     var sorted = channelList 
     .OrderBy(x=>keys[x.id]); 
    #endregion client-side ordering 

    #region paging 
     var results = sorted 
     .Skip(skip) 
     .Take(pageSize) 
     .ToList(); 
    #endregion paging 

In diesem Fall Wenn ein Datensatz hinzugefügt (neue höhere ID) oder gelöscht (ID entfernt) wird, wird die Reihenfolge so beibehalten, als ob der Datensatz immer existiert hätte, sodass sich die Ergebnisse zwar verschieben, aber nicht vollständig neu geordnet werden. Auch die Leistung wird wahrscheinlich schlecht sein, wenn die ID des Kanals groß ist. In den meisten Fällen würde ich nur vorschlagen, eine Zufallszahl zu verwenden, die unpagierten Ergebnisse zu generieren und dann die Ergebnisse mit diesem Schlüssel für nachfolgende Paging - Operationen in den Cache zu stopfen (wenn das Senden des gesamten Ergebnisses nicht an den Client gesendet wird) Möglichkeit).

Verwandte Themen