3 Stimmen

LINQ verwenden, um einen zufälligen XML-Knoten auszuwählen

Ich bin neu bei LINQ und habe ein Problem. Ich habe eine Datei, die in etwa wie folgt aussieht:

<?xml version="1.0" encoding="utf-8" ?>
<Galleries>
   <Gallery ID="10C31804CEDB42693AADD760C854ABD" Title="Test1">
      <Description>The first test gallery.  Picture of a cat and Wilford Brimley.  Can you tell the difference?</Description>
      <Images>
         <Image Title="t1Image1" FileName="tcats.jpg" />
         <Image Title="t1Image2" FileName="twb.jpg" />
      </Images>
   </Gallery>
   <Gallery ID="0420EC15405B488E1E0F157AC823A6" Title="Test2">
      <Description>The second test gallery.  A large image of Wilford Brimley and various cats.  The cats will be on the right.</Description>
      <Images>
         <Image Title="t2Image1" FileName="wilfordbrimley.jpg" />
      </Images>
   </Gallery>
</Galleries> 

Wie auch immer, ich kenne die ID der Galerie, die ich will, aber ich möchte eines der Bilder nach dem Zufallsprinzip auswählen. Gibt es eine LINQ-Anweisung, die dies tun kann?

3voto

John Boker Punkte 80493

Können Sie die Bilder in der Galerie mit Random.Next() ordnen und dann das erste Element auswählen.

Ich weiß nicht viel über linq2xml aber hier ist, was ich kam mit

static void Main(string[] args)
{
    Random rnd = new Random();
    XDocument galleries = XDocument.Load(@"C:\Users\John Boker\Documents\Visual Studio 2008\Projects\ConsoleApplication1\ConsoleApplication1\Galleries.xml");
    var image = (from g in galleries.Descendants("Gallery")
                 where g.Attribute("ID").Value == "10C31804CEDB42693AADD760C854ABD"
                 select g.Descendants("Images").Descendants("Image").OrderBy(r=>rnd.Next()).First()).First();
    Console.WriteLine(image);
    Console.ReadLine();
}

Ich bin mir sicher, dass man das Auswählen auch anders machen könnte, aber so habe ich es gemacht, damit es mit dem random.next Ding funktioniert.

1voto

Steve Guidi Punkte 19012

Hier sind ein paar Lösungen, die auf der Berechnung der Anzahl von Image Knoten; nicht furchtbar effizient, aber ich glaube nicht, dass man es besser machen kann, da viele Linq-Sammlungstypen ausgesetzt sind als IEnumerable .

XElement GetRandomImage(XElement images)
{
    Random rng = new Random();
    int numberOfImages = images.Elements("Image").Count();

    return images.Elements("Image").Skip(rng.Next(0, numberOfImages)).FirstOrDefault();
}

XElement GetRandomImage(XElement images)
{
    Random rng = new Random();
    IList<XElement> images = images.Elements("Image").ToList();

    return images.Count == 0 :
        null ?
        images[rng.Next(0, images.Count - 1)];
}

0voto

jason Punkte 227577

Ich empfehle nicht, die ausgewählte Antwort zu verwenden, da sie eine Sortierung verwendet, die O(n log n) donde n ist die Anzahl der Bilder in der ausgewählten Galerie. Sie können ein zufälliges Element aus einer Liste in O(1) Zeit. Daher würde ich das Folgende verwenden:

using(StreamReader sr = new StreamReader(File.Open(path, FileMode.Open))) {
    XDocument galleries = XDocument.Load(sr);
    string id = "10C31804CEDB42693AADD760C854ABD";
    var query = (from gallery in galleries.Descendants("Galleries")
                                          .Descendants("Gallery")
                 where (string)gallery.Attribute("ID") == id
                 select gallery.Descendants("Images")
                               .Descendants("Image")
                ).SingleOrDefault();
    Random rg = new Random();
    var image = query.ToList().RandomItem(rg);
    Console.WriteLine(image.Attribute("Title"));
}

Hier verwende ich:

static class ListExtensions {
    public static T RandomItem<T>(this List<T> list, Random rg) {
        if(list == null) {
            throw new ArgumentNullException("list");
        }
        if(rg == null) {
            throw new ArgumentNullException("rg");
        }
        int index = rg.Next(list.Count);
        return list[index];
    }
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X