C# 使用LINQ选择随机XML节点

C# 使用LINQ选择随机XML节点,c#,xml,linq,C#,Xml,Linq,我是LINQ的新手,有个问题。我有一个类似以下内容的文件: <?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

我是LINQ的新手,有个问题。我有一个类似以下内容的文件:

<?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> 

第一个测试库。一只猫和威尔福德·布里姆利的照片。你能分辨出区别吗?
第二个测试库。威尔福德·布里姆利和各种猫的大照片。猫在右边。

无论如何,我知道我想要的画廊的ID,但我想随机选择一张图片。是否有LINQ语句可以做到这一点?

您可以随机对库中的图像进行排序。下一步()然后选择第一个元素

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

我相信选择可以做很多不同的事情,但这就是我所做的,让它与随机一起工作。下一件事。

这里有几个解决方案,它们依赖于计算
图像
节点的数量;效率不太高,但我认为您不能做得更好,因为许多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<XElement> images = images.Elements("Image").ToList();

    return images.Count == 0 :
        null ?
        images[rng.Next(0, images.Count - 1)];
}
XElement GetRandomImage(XElement图像)
{
随机rng=新随机();
int numberOfImages=images.Elements(“Image”).Count();
返回images.Elements(“Image”).Skip(rng.Next(0,numberOfImages)).FirstOrDefault();
}
XElement GetRandomImage(XElement图像)
{
随机rng=新随机();
IList images=images.Elements(“Image”).ToList();
返回图像。计数==0:
无效的
图像[rng.Next(0,图像计数-1)];
}

我不建议使用所选答案,因为它使用的排序是
O(n log n)
,其中
n
是所选库中的图像数。您可以从
O(1)
time中的列表中选择一个随机项。因此,我将使用以下方法:

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<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];
    }
}
静态类ListExtensions{
公共静态T随机项(此列表,随机rg){
if(list==null){
抛出新的ArgumentNullException(“列表”);
}
if(rg==null){
抛出新的ArgumentNullException(“rg”);
}
int index=rg.Next(list.Count);
返回列表[索引];
}
}

我知道了如何使用Random.Next()来选择随机图库,但如何在给定图库ID的图库下选择随机图像?很抱歉,LINQ现在正困扰着我。@奥斯曼:如果你有一个
XElement
XNode
包含图库,只需使用
node.Element(“图像”)
获取图像元素。这太奇怪了,我已经发布了一个关于它的问题: