2010-01-14 103 views
3

我是LINQ的新手,並且遇到問題。我有一個看起來是這樣的文件:使用LINQ來選擇一個隨機XML節點

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

回答

3

您可以通過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(); 
} 

我敢肯定的選擇可以不同方式做了很多,但是這就是我所做的,以使其與隨機工作。下一件事。

+0

一個非常聰明的解決方案。 – 2010-01-14 00:23:57

+0

我想出瞭如何使用Random.Next()來選擇一個隨機圖庫,但是如何在給定圖庫ID的圖庫下選擇一個隨機圖像? 對不起,LINQ現在正在審查我的頭。 – 2010-01-14 00:29:22

+1

@OSMan:如果你有一個包含Gallery的'XElement'或'XNode',只需使用'node.Element(「Images」)'獲取圖像元素。 – 2010-01-14 00:34:35

1

這裏有幾個解決方案依賴於計算節點的數量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<XElement> images = images.Elements("Image").ToList(); 

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

我不推薦使用選定的答案,因爲它使用一種是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<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]; 
    } 
}