使用LINQ选择随机XML节点

我是LINQ的新手,遇到了问题。 我有一个看起来像这样的文件:

   The first test gallery. Picture of a cat and Wilford Brimley. Can you tell the difference?       The second test gallery. A large image of Wilford Brimley and various cats. The cats will be on the right.      

无论如何,我知道我想要的画廊的ID,但我想随机选择其中一个图像。 是否有可以执行此操作的LINQ语句?

您可以通过Random.Next()在图库中订购图像,然后选择第一个元素。

我不太了解linq2xml,但这是我想出的

 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(); } 

我确信选择可以做很多不同的事情,但这就是我用它来处理random.next的事情。

以下是一些依赖于计算Image节点数量的解决方案; 不是非常有效,但我不认为你可以做得更好,因为许多Linq集合类型暴露为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 images = images.Elements("Image").ToList(); return images.Count == 0 : null ? images[rng.Next(0, images.Count - 1)]; } 

我不建议使用所选答案,因为它使用的排序为O(n log n) ,其中n是所选图库中的图像数。 您可以在O(1)时间内从列表中选择随机项。 因此,我会使用以下内容:

 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")); } 

我在这里使用:

 static class ListExtensions { public static T RandomItem(this List 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]; } }