Мой код очень неэффективен для этого простого использования Linq - PullRequest
1 голос
/ 07 июля 2010

У меня есть следующий метод, который должен анализировать информацию из XML-ответа и возвращать коллекцию пользователей.

Я решил создать класс Friend и вернуть List<Friend> вызывающему методу.

Вот что у меня есть, но я заметил, что метод ids.ToList (). Count анализирует каждый элемент id в List, а затем делает это снова в условном выражении for.Это просто супер неэффективно.

public List<Friend> FindFriends()
{
    List<Friend> friendList = new List<Friend>();

    var friends = doc.Element("ipb").Element("profile").Element("friends").Elements("user");
    var ids = from fr in friends
              select fr.Element("id").Value;

    var names = from fr in friends
                select fr.Element("name").Value;

    var urls = from fr in friends
                select fr.Element("url").Value;

    var photos = from fr in friends
                select fr.Element("photo").Value;

    if (ids.ToList().Count > 0)
    {
        for (int i = 0; i < ids.ToList().Count; i++)
        {
            Friend buddy = new Friend();
            buddy.ID = ids.ToList()[i];
            buddy.Name = names.ToList()[i];
            buddy.URL = urls.ToList()[i];
            buddy.Photo = photos.ToList()[i];

            friendList.Add(buddy);
        }
    }            

    return friendList;
}

Ответы [ 2 ]

10 голосов
/ 07 июля 2010

Первый вопрос - нужно ли возвращать List<Friend>?Вы можете вернуть IEnumerable<Friend> вместо этого?Если это так, производительность становится намного лучше:

IEnumerable<Friend> FindFriends()
{
    return doc.Descendants("user").Select(user => new Friend {
        ID = user.Element("id").Value,
        Name = user.Element("name").Value,
        Url = user.Element("url").Value,
        Photo = user.Element("photo").Value
    });
}

Вместо того, чтобы фактически создавать новые сегменты и вставлять в них значения, это создает проекцию или новый объект, который просто содержит вселогика для как создавать новые объекты Friend без фактического их создания.Они создаются, когда вызывающий в конечном итоге начинает foreach через IEnumerable.Это называется «отложенное выполнение».

Это также предполагает одно предположение - все узлы <user> в вашем фрагменте XML являются друзьями.Если это не так, первая часть выделения XML может быть немного сложнее немного .

И, как указывает @anon, даже если вам нужно вернутьList<Friend> по некоторым причинам, не очевидным из предоставленной вами информации, вы можете просто позвонить .ToList() в конце оператора возврата.Это просто выполнит проекцию, которую я описал выше, прямо в новое ведро, поэтому вы создадите только один.

0 голосов
/ 07 июля 2010

Зачем вам нужны отдельные переменные ids / names / urls / photos?Объедините все это.Вы можете исключить вызов ToList (), если вам не нужен List.

List<Friend> friendList = (from f in doc.Element("ipb").Element("profile").Element("friends").Elements("user")
                          select new Friend() { 
                                                 ID = f.Element("id").Value, 
                                                 Name = f.Element("name").Value,
                                                 URL = f.Element("url").Value,
                                                 Photo = f.Element("photo").Value
                                 }).ToList();

return friendList;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...