2009-12-29 51 views
1

下面的代碼工作正常,但我想使用yield或通過更改算法來優化代碼。使用良率或更改算法優化代碼

public IEnumerable<Book> GetAuthorWithBookName(string keyword) 
{ 
    var bookAndAuthorList = new List<Book>(); 
    List<Author> AuthorNameList = getAuthorName(keyword); 
    foreach (var author in AuthorNameList) 
    { 
     XmlNode booksNames = getBook(author); 
     XDocument XDOCbooksNames = XDocument.Parse(booksNames.OuterXml); 

     var bookNameList = (
      from x1 in XDOCbooksNames.Descendants("Books") 
      select x1.Elements("book").Select(g => g.Attribute("name").Value)) 
      .ToList(); 
     foreach (var bookName in bookNameList) 
     { 
      bookAndAuthorList.Add(new Book() 
      { 
       authorName = author.authorName, 
       bookName = bookName 
      }); 
     } 
    } 
    return bookAndAuthorList; 
} 

public class Book 
{ 
    public string authorName { get; set; } 
    public string bookName { get; set; } 
} 
+0

使用'yield'不會給你一個真正的好處,因爲無論如何你會在每次迭代中創建一個新的'Book'對象。 – 2009-12-29 23:24:22

+1

@Aviad,如果在循環中存在一個退出條件,可以提供幫助,其中Book實例被消耗 – 2009-12-29 23:29:53

+2

爲什麼優化?爲什麼? – LukeH 2009-12-29 23:32:37

回答

6

作爲一個快速取勝,你可以刪除.ToList()呼叫。你所做的只是列舉項目,所以沒有必要這樣做。同樣,不需要創建bookAndAutherList。

最後,我想你可以剝離下來到這一點:

public IEnumerable<Book> GetAuthorWithBookName(string keyword) 
{ 
    return from author in getAuthorName(keyword) 
      let book = getBook(author) 
      from xmlBook in XDocument.Parse(book.OuterXml).Descendants("Books") 
      select new Book 
      { 
       authorName = author.AuthorName, 
       bookName = xmlBook.Attribute("name").Value 
      }; 
} 
+1

這是最好的迴應。 +1。 @NETQuestion:LINQ自動構建實現延遲迭代的IEnumerable查詢(即在迭代過程中使用yield關鍵字)。只要您可以將數據源保存在內存中,並且您的代碼肯定意味着您可以執行此操作,那麼只需返回LINQ查詢本身就可以了。 – Randolpho 2009-12-29 23:46:20

+2

另外,我想提一下,令人驚訝的是使用不足。另一個+1的隨機答案只是提及它! :) – Randolpho 2009-12-30 00:23:33

+1

+1「let」 - 我只是想「等等,是F#還是什麼?」 - LINQ本身就是一門語言。 – 2009-12-30 02:53:12

0

試試這個:

foreach (var bookName in bookNameList) 
{ 
    yield return new Book() 
    { 
     authorName = author.authorName, 
     bookName = bookName 
    }; 
} 

,並刪除其他return聲明。

1

不知道你會得到很多'優化'。如果您經常使用正在生成的枚舉中途中斷,那麼收益率會更好,這樣您就不會進行不必要的計算。但在這裏:

這是未經測試。

public IEnumerable<Book> GetAuthorWithBookName(string keyword) 
{ 
    foreach (var author in getAuthorName(keyword)) 
    { 
     XDocument XDOCbooksNames = XDocument.Parse(getBook(author).OuterXml); 

     var bookNameList = from x1 in XDOCbooksNames.Descendants("Books") 
          select x1.Elements("book").Select(g => g.Attribute("name").Value); 

     foreach (var bookName in bookNameList) 
     { 
      yield return new Book() 
       { 
        authorName = author.authorName, 
        bookName = bookName 
       }; 
     } 
    } 
} 

我做了什麼:

  1. 取出ToList()在 表達,它已經返回 枚舉。通過 鞏固getAuthorName到 的foreach去掉了一些代碼(注意 - 確保功能的產量和IEnumerable過,如果可以的話)
  2. 產量的回報,而不是添加到列表
9

迴應魯本斯和盧克正確講解使用產量。

但是,這看起來對我很可疑。

XmlNode booksNames = getBook(author); 
XDocument XDOCbooksNames = XDocument.Parse(booksNames.OuterXml); 

您將XML轉換爲字符串,然後再分析它,只是因爲你想它從DOM節點轉換Xml.Linq節點。如果你在談論優化,那麼這比創建一個額外的列表效率低得多。

+1

好點,如果我有更多upvotes,我會+1! – 2009-12-29 23:42:21

+2

看起來最好的解決方案是獲得getBook的實現,該實現返回一個'XElement'或'XDocument' – 2009-12-29 23:45:35

+0

+1,很好! – 2009-12-29 23:46:37